package advanced.drawing; import java.util.HashMap; import org.mt4j.MTApplication; import org.mt4j.components.TransformSpace; import org.mt4j.components.visibleComponents.shapes.AbstractShape; import org.mt4j.input.IMTInputEventListener; import org.mt4j.input.inputData.AbstractCursorInputEvt; import org.mt4j.input.inputData.InputCursor; import org.mt4j.input.inputData.MTInputEvent; import org.mt4j.sceneManagement.AbstractScene; import org.mt4j.sceneManagement.IPreDrawAction; import org.mt4j.util.MTColor; import org.mt4j.util.math.ToolsMath; import org.mt4j.util.math.Vector3D; import processing.core.PApplet; public class DrawSurfaceScene extends AbstractScene { private MTApplication mtApp; private AbstractShape drawShape; private float stepDistance; private Vector3D localBrushCenter; private float brushWidthHalf; private HashMap<InputCursor, Vector3D> cursorToLastDrawnPoint; private float brushHeightHalf; private float brushScale; private MTColor brushColor; private boolean dynamicBrush; //TODO only works as lightweight scene atm because the framebuffer isnt cleared each frame //TODO make it work as a heavywight scene //TODO scale smaller at higher speeds? //TODO eraser? //TODO get blobwidth from win7 touch events and adjust the brush scale public DrawSurfaceScene(MTApplication mtApplication, String name) { super(mtApplication, name); this.mtApp = mtApplication; this.getCanvas().setDepthBufferDisabled(true); /* this.drawShape = getDefaultBrush(); this.localBrushCenter = drawShape.getCenterPointLocal(); this.brushWidthHalf = drawShape.getWidthXY(TransformSpace.LOCAL)/2f; this.brushHeightHalf = drawShape.getHeightXY(TransformSpace.LOCAL)/2f; this.stepDistance = brushWidthHalf/2.5f; */ this.brushColor = new MTColor(0,0,0); this.brushScale = 1.0f; this.dynamicBrush = true; // this.stepDistance = 5.5f; this.cursorToLastDrawnPoint = new HashMap<InputCursor, Vector3D>(); this.getCanvas().addInputListener(new IMTInputEventListener() { public boolean processInputEvent(MTInputEvent inEvt){ if(inEvt instanceof AbstractCursorInputEvt){ final AbstractCursorInputEvt posEvt = (AbstractCursorInputEvt)inEvt; final InputCursor m = posEvt.getCursor(); // System.out.println("PrevPos: " + prevPos); // System.out.println("Pos: " + pos); if (posEvt.getId() != AbstractCursorInputEvt.INPUT_ENDED){ registerPreDrawAction(new IPreDrawAction() { public void processAction() { boolean firstPoint = false; Vector3D lastDrawnPoint = cursorToLastDrawnPoint.get(m); Vector3D pos = new Vector3D(posEvt.getPosX(), posEvt.getPosY(), 0); if (lastDrawnPoint == null){ lastDrawnPoint = new Vector3D(pos); cursorToLastDrawnPoint.put(m, lastDrawnPoint); firstPoint = true; }else{ if (lastDrawnPoint.equalsVector(pos)) return; } float scaledStepDistance = stepDistance*brushScale; Vector3D direction = pos.getSubtracted(lastDrawnPoint); float distance = direction.length(); direction.normalizeLocal(); direction.scaleLocal(scaledStepDistance); float howManySteps = distance/scaledStepDistance; int stepsToTake = Math.round(howManySteps); //Force draw at 1st point if (firstPoint && stepsToTake == 0){ stepsToTake = 1; } // System.out.println("Steps: " + stepsToTake); // GL gl = Tools3D.getGL(mtApp); // gl.glBlendFuncSeparate(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA, GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA); mtApp.pushMatrix(); //We would have to set up a default view here for stability? (default cam etc?) getSceneCam().update(); Vector3D currentPos = new Vector3D(lastDrawnPoint); for (int i = 0; i < stepsToTake; i++) { //start i at 1? no, we add first step at 0 already currentPos.addLocal(direction); //Draw new brush into FBO at correct position Vector3D diff = currentPos.getSubtracted(localBrushCenter); mtApp.pushMatrix(); mtApp.translate(diff.x, diff.y); //FIXME works only if brush upper left at 0,0 mtApp.translate(brushWidthHalf, brushHeightHalf); mtApp.scale(brushScale); if (dynamicBrush){ //Rotate brush randomly // mtApp.rotateZ(PApplet.radians(Tools3D.getRandom(0, 179))); // mtApp.rotateZ(PApplet.radians(Tools3D.getRandom(-85, 85))); mtApp.rotateZ(PApplet.radians(ToolsMath.getRandom(-25, 25))); // mtApp.rotateZ(PApplet.radians(Tools3D.getRandom(-9, 9))); mtApp.translate(-brushWidthHalf, -brushHeightHalf); } /* //Use random brush from brushes int brushIndex = Math.round(Tools3D.getRandom(0, brushes.length-1)); AbstractShape brushToDraw = brushes[brushIndex]; */ AbstractShape brushToDraw = drawShape; //Draw brush brushToDraw.drawComponent(mtApp.g); mtApp.popMatrix(); } mtApp.popMatrix(); cursorToLastDrawnPoint.put(m, currentPos); } public boolean isLoop() { return false; } }); }else{ cursorToLastDrawnPoint.remove(m); } } return false; } }); } public void setBrush(AbstractShape brush){ this.drawShape = brush; this.localBrushCenter = drawShape.getCenterPointLocal(); this.brushWidthHalf = drawShape.getWidthXY(TransformSpace.LOCAL)/2f; this.brushHeightHalf = drawShape.getHeightXY(TransformSpace.LOCAL)/2f; this.stepDistance = brushWidthHalf/2.8f; this.drawShape.setFillColor(this.brushColor); this.drawShape.setStrokeColor(this.brushColor); } public void setBrushColor(MTColor color){ this.brushColor = color; if (this.drawShape != null){ drawShape.setFillColor(color); drawShape.setStrokeColor(color); } } public void setBrushScale(float scale){ this.brushScale = scale; } public void init() { } public void shutDown() { } }