package nbtool.gui.logviews.misc; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import javax.swing.JPanel; import nbtool.data.calibration.ColorParam; import nbtool.data.log.Block; import nbtool.data.log.Log; import nbtool.gui.utilitypanes.UtilityManager; import nbtool.images.YUYV8888Image; import nbtool.io.CommonIO.IOFirstResponder; import nbtool.io.CommonIO.IOInstance; import nbtool.nio.CrossServer; import nbtool.nio.CrossServer.CrossInstance; import nbtool.util.Debug; import nbtool.util.SharedConstants; public abstract class VisionView extends ViewParent implements IOFirstResponder { public static final String DEFAULT_VISION_FUNCTION_NAME = "Vision"; /* you must implement this! */ protected abstract void setupVisionDisplay(); /* you may override these! */ //determines what function 'callVision()' executes protected String functionName() { return DEFAULT_VISION_FUNCTION_NAME; } /* if returns true, callVision() will check ColorCalibrationUtility * and use the most recent ColorParam if such exists (and is global) */ protected boolean shouldUseGlobalColorParams() { return true; } //Should VisionView call setupVisionDisplay() if no NBCross instance is found? protected boolean continueIfNoNBCross() { return false; } /****** * These variables and methods are provided as helpers. */ /* latest from nbcross */ protected Log latestVisionLog = null; protected final boolean callVision() { return callVision(displayedLog); } protected final boolean callVision(Log with) { CrossInstance ci = CrossServer.instanceByIndex(0); if (ci == null) return false; final boolean useGlobal = this.shouldUseGlobalColorParams(); Log sentToNbcross = null; if (useGlobal && UtilityManager.ColorCalibrationUtility.getLatest() != null && UtilityManager.ColorCalibrationUtility.appliedGlobally() ) { sentToNbcross = this.displayedLog.deepCopy(); ColorParam.Set latest = UtilityManager.ColorCalibrationUtility.getLatest(); sentToNbcross.topLevelDictionary.put("ModifiedColorParams", latest.get(this.isTop()).serialize()); } else { sentToNbcross = this.displayedLog; } assert(ci.tryAddCall(new IOFirstResponder(){ @Override public void ioFinished(IOInstance instance) { outer.ioFinished(instance); } @Override public void ioReceived(IOInstance inst, int ret, Log... out) { assert(out.length == 1); assert(out[0].logClass.equals("VisionReturn")); latestVisionLog = out[0]; outer.ioReceived(inst, ret, out); } @Override public boolean ioMayRespondOnCenterThread(IOInstance inst) { return false; } }, functionName(), sentToNbcross)); return true; } protected final YUYV8888Image getOriginal() { return displayedLog.blocks.get(0).parseAsYUVImage(); } protected final byte[] originalImageBytes() { return displayedLog.blocks.get(0).data; } protected final boolean isTop() { String wf0 = displayedLog.blocks.get(0).whereFrom; if (wf0.equals("camera_TOP")) return true; if (wf0.equals("camera_BOT")) return false; throw new RuntimeException("tripoint image block had invalid type: " + wf0); } protected final int originalWidth() { return displayedLog.blocks.get(0).dict. get(SharedConstants.LOG_BLOCK_IMAGE_WIDTH_PIXELS()).asNumber().asInt(); } protected final int originalHeight() { return displayedLog.blocks.get(0).dict. get(SharedConstants.LOG_BLOCK_IMAGE_HEIGHT_PIXELS()).asNumber().asInt(); } protected final Block getYBlock() { return latestVisionLog == null ? null : latestVisionLog.find("yBuffer"); } protected final Block getWhiteBlock() { return latestVisionLog == null ? null : latestVisionLog.find("whiteRet"); } protected final Block getGreenBlock() { return latestVisionLog == null ? null : latestVisionLog.find("greenRet"); } protected final Block getOrangeBlock() { return latestVisionLog == null ? null : latestVisionLog.find("orangeRet"); } protected final Block getSegmentedBlock() { return latestVisionLog == null ? null : latestVisionLog.find("segBuffer"); } protected final Block getEdgeBlock() { return latestVisionLog == null ? null : latestVisionLog.find("edgeBuffer"); } protected final Block getLineBlock() { return latestVisionLog == null ? null : latestVisionLog.find("lineBuffer"); } protected final Block getBallBlock() { if (latestVisionLog != null) { for (Block b : latestVisionLog.blocks) { if (b.type.equals(SharedConstants.SexprType_DEFAULT()) && b.whereFrom.equals("nbcross-Vision-ball")) return b; } } return null; } protected final Block getWhiteSpotBlock() { if (latestVisionLog != null) { for (Block b : latestVisionLog.blocks) { if (b.type.equals(SharedConstants.SexprType_DEFAULT()) && b.whereFrom.equals("nbcross-Vision-spot-white")) return b; } } return null; } protected final Block getBlackSpotBlock() { if (latestVisionLog != null) { for (Block b : latestVisionLog.blocks) { if (b.type.equals(SharedConstants.SexprType_DEFAULT()) && b.whereFrom.equals("nbcross-Vision-spot-black")) return b; } } return null; } protected final Block getCCDBlock() { return latestVisionLog == null ? null : latestVisionLog.find("ccdBuffer"); } protected final Block getDebugImageBlock() { return latestVisionLog == null ? null : latestVisionLog.find("debugImage"); } /****** * Begin internal implementation. */ final VisionView outer = this; @Override public final String[] displayableTypes() { return new String[]{SharedConstants.LogClass_Tripoint()}; } @Override public final boolean ioMayRespondOnCenterThread(IOInstance inst) { return false; } @Override public final void setupDisplay() { if (callVision() || continueIfNoNBCross()) { setupVisionDisplay(); } else { Debug.error("%s view not loading because it could not call Vision()", this.getClass().getName()); this.setLayout(null); final NBCrossErrorPane errorPanel = new NBCrossErrorPane(); this.add(errorPanel); this.addComponentListener(new ComponentListener(){ @Override public void componentResized(ComponentEvent e) {reset(errorPanel);} @Override public void componentMoved(ComponentEvent e) {reset(errorPanel);} @Override public void componentShown(ComponentEvent e) {reset(errorPanel);} @Override public void componentHidden(ComponentEvent e) {reset(errorPanel);} }); } } private final void reset(NBCrossErrorPane panel) { panel.setBounds(10,10,this.getSize().width - 20, this.getSize().height - 20); } private class NBCrossErrorPane extends JPanel { @Override public void paintComponent(Graphics g) { g.setColor(Color.DARK_GRAY); g.fillRect(0, 0, this.getSize().width, this.getSize().height); g.setColor(Color.RED); Font use = this.getFont().deriveFont(24.0f); g.setFont(use); g.drawString("could not connect to NBCross!", 50, 50); } } }