Add removal mechanism for signal wires.

This commit is contained in:
Sergio Martínez Portela 2020-06-01 15:07:48 +02:00
parent a2bcf79309
commit 8b3bbfee78
4 changed files with 154 additions and 35 deletions

View File

@ -13,11 +13,14 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.codigoparallevar.minicards.motion.MotionMode;
import com.codigoparallevar.minicards.parts.connectors.SignalRoundOutputConnector;
import com.codigoparallevar.minicards.types.Part;
import com.codigoparallevar.minicards.types.PartConnection;
import com.codigoparallevar.minicards.types.PartGrid;
import com.codigoparallevar.minicards.types.Position;
import com.codigoparallevar.minicards.types.Selectable;
import com.codigoparallevar.minicards.types.connectors.Wiring.SignalWire;
import com.codigoparallevar.minicards.types.connectors.Wiring.Wire;
import com.codigoparallevar.minicards.types.connectors.input.AnyInputConnector;
import com.codigoparallevar.minicards.types.connectors.input.BooleanInputConnector;
import com.codigoparallevar.minicards.types.connectors.input.InputConnector;
@ -35,6 +38,7 @@ import java.util.List;
import java.util.Map;
public class CanvasView extends View implements PartGrid {
private static final String LogTag = "Canvas view";
@NonNull
List<Part> parts = new ArrayList<>();
@ -92,7 +96,7 @@ public class CanvasView extends View implements PartGrid {
Map<String, Part> partsById = buildPartsById();
for (PartConnection connection : connections){
if (!partsById.containsKey(connection.inputPartId)){
Log.e("Canvas view", "Key '" + connection.inputPartId
Log.e(LogTag, "Key '" + connection.inputPartId
+ "' not found on deserialization");
continue;
}
@ -101,14 +105,14 @@ public class CanvasView extends View implements PartGrid {
InputConnector inputConnector = inputPart.getConnectorWithId(connection.inputConnectorId);
if (inputConnector == null){
Log.e("Canvas view", "Connector ID '" + connection.inputConnectorId
Log.e(LogTag, "Connector ID '" + connection.inputConnectorId
+ "' not found on deserialization");
continue;
}
OutputConnector outputConnector = connection.outputConnector;
if (inputConnector == null){
Log.e("Canvas view", "Connector not found on connection");
Log.e(LogTag, "Connector not found on connection");
continue;
}
@ -120,7 +124,7 @@ public class CanvasView extends View implements PartGrid {
outputConnector.connectTo(inputConnector);
}
catch (ClassCastException e) {
Log.e("Minicards - Canvas view", "Malformed connection", e);
Log.e(LogTag, "Malformed connection", e);
}
}
}
@ -129,7 +133,7 @@ public class CanvasView extends View implements PartGrid {
Map<String, Part> partsById = new HashMap<>(parts.size());
for (Part part : parts) {
partsById.put(part.get_id(), part);
Log.w("CanvasView", "Added part ID: " + part.get_id() + " - " + part);
Log.w(LogTag, "Added part ID: " + part.get_id() + " - " + part);
}
return partsById;
@ -146,7 +150,7 @@ public class CanvasView extends View implements PartGrid {
part.draw(scrolledCanvas, _devMode);
}
// Log.d("Render time", System.currentTimeMillis() - renderStartTime + "ms");
Log.v(LogTag, "Render time: " + (System.currentTimeMillis() - renderStartTime) + "ms");
}
private void drawBackground(ScrolledCanvas canvas) {
@ -190,11 +194,21 @@ public class CanvasView extends View implements PartGrid {
lastTouchedPosition.to(xInScreen, yInScreen);
lastTouchedTime = System.currentTimeMillis();
if (selectedPart == null) {
Log.d("Touched part", "not found");
Log.d(LogTag, "Touched part not found");
return false;
}
if (selectedPart instanceof Wire) {
// No drag or long-touch, just show the "cut" option
// TODO:
Log.d(LogTag, "Touched Wire");
Wire selectedWire = (Wire) selectedPart;
selectedPart = null;
Log.d("Touched part", "Part: " + selectedPart);
selectedWire.unlink();
}
else {
Log.d(LogTag, "Touched part FOUND. Part: " + selectedPart);
}
}
break;
@ -215,7 +229,7 @@ public class CanvasView extends View implements PartGrid {
selectedPart.getMoveable().drop(xInCanvas, yInCanvas);
if (inDropZone(xInScreen, yInScreen)) {
Log.d("Canvas", "Deleting element" + selectedPart);
Log.d(LogTag, "Deleting element" + selectedPart);
parts.remove(selectedPart);
selectedPart.unlink();
}
@ -230,7 +244,7 @@ public class CanvasView extends View implements PartGrid {
try {
saveState();
} catch (IOException e) {
Log.w("PartCanvasView", e.getMessage());
Log.w(LogTag, e.getMessage());
}
break;
@ -240,7 +254,7 @@ public class CanvasView extends View implements PartGrid {
break;
}
Log.d("CanvasView", "Moving part="+selectedPart);
// Log.v(LogTag, "Moving part="+selectedPart);
if (selectedPart == null){
int xMovement = _mouseDownPoint.item1 - xInScreen;
int yMovement = _mouseDownPoint.item2 - yInScreen;
@ -251,7 +265,7 @@ public class CanvasView extends View implements PartGrid {
_mouseDownPoint = new Tuple2(xInScreen, yInScreen);
}
else {
Log.d("Canvas", "X: " + xInScreen + " Y: " + yInScreen
Log.d(LogTag, "X: " + xInScreen + " Y: " + yInScreen
+ " in drop zone " + _dropToRemoveZone + " : "
+ inDropZone(xInScreen, yInScreen));
@ -273,7 +287,7 @@ public class CanvasView extends View implements PartGrid {
default:
{
Log.d("PartCanvasView", "Unhandled action: " + event.getAction());
Log.d(LogTag, "Unhandled action: " + event.getAction());
}
}
@ -337,12 +351,35 @@ public class CanvasView extends View implements PartGrid {
}
}
// Then with input ones
List<InputConnector> inputConnectors = part.getInputConnectors();
if (inputConnectors != null) {
for (InputConnector inputConnector : inputConnectors) {
if (inputConnector.containsPoint(x, y)) {
return inputConnector;
// // Then with input ones
// List<InputConnector> inputConnectors = part.getInputConnectors();
// if (inputConnectors != null) {
// for (InputConnector inputConnector : inputConnectors) {
// if (inputConnector.containsPoint(x, y)) {
// return inputConnector;
// }
// }
// }
}
// Finally, try with the wires
for (int i = parts.size() - 1; i >= 0; i--) {
final Part part = parts.get(i);
List<OutputConnector> outputConnectors = part.getOutputConnectors();
if (outputConnectors != null) {
for (OutputConnector outputConnector : outputConnectors) {
if (outputConnector instanceof SignalRoundOutputConnector) {
SignalRoundOutputConnector conn = (SignalRoundOutputConnector) outputConnector;
List<SignalWire> wires = conn.getWires();
if (wires == null) {
continue;
}
for (Wire wire : wires) {
if (wire.containsPoint(x, y)) {
Log.d(LogTag, "Point in wire " + wire);
return wire;
}
}
}
}
}

View File

@ -230,12 +230,10 @@ public class CardActivity extends AppCompatActivity {
devFabMenu.setVisibility(View.GONE);
userFabMenu.setVisibility(View.GONE);
((View)removePartFab).setVisibility(View.VISIBLE);
Log.d("Main", "Changing visibility!");
}
else {
this.setDevMode(devMode);
((View)removePartFab).setVisibility(View.GONE);
Log.d("Main", "Now changing visibility!");
}
canvasView.setDropZone(
removePartFab.getX(), removePartFab.getX() + removePartFab.getWidth(),

View File

@ -20,6 +20,8 @@ import java.util.List;
public class SignalRoundOutputConnector implements Drawable, SignalOutputConnector,
RoundOutputConnector<Signal, SignalInputConnector, SignalWire> {
private static final String LogTag = "RoundOutputConnector";
private PartGrid _partGrid;
private int _centerX;
private int _centerY;
@ -71,7 +73,7 @@ public class SignalRoundOutputConnector implements Drawable, SignalOutputConnect
SignalInputConnector resultPoint = _partGrid.getSignalInputConnectorOn(
wire.getXEnd(), wire.getYEnd());
Log.d("RoundOutputConnector", "Dropped wire on " + resultPoint);
Log.d(LogTag, "Dropped wire on " + resultPoint);
// Not connected
if (resultPoint == null){
@ -88,7 +90,7 @@ public class SignalRoundOutputConnector implements Drawable, SignalOutputConnect
_wires.add(wire);
}
else {
Log.w("RoundOutputConnector",
Log.w(LogTag,
"Asked to drop non matching wire "
+ "(expected " + _currentWire + ", got " + wire + ")");
}
@ -97,6 +99,7 @@ public class SignalRoundOutputConnector implements Drawable, SignalOutputConnect
@Override
public void unlinkWire(SignalWire wire) {
_wires.remove(wire);
_connections.remove(wire.getAttachedTo());
}
@Override
@ -173,4 +176,8 @@ public class SignalRoundOutputConnector implements Drawable, SignalOutputConnect
public float getRadius() {
return _radius;
}
public List<SignalWire> getWires() {
return this._wires;
}
}

View File

@ -3,23 +3,28 @@ package com.codigoparallevar.minicards.types.connectors.Wiring;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import com.codigoparallevar.minicards.ScrolledCanvas;
import com.codigoparallevar.minicards.types.Drawable;
import com.codigoparallevar.minicards.types.Dropper;
import com.codigoparallevar.minicards.types.Moveable;
import com.codigoparallevar.minicards.types.Selectable;
import com.codigoparallevar.minicards.types.connectors.input.InputConnector;
import com.codigoparallevar.minicards.types.connectors.output.OutputConnector;
import com.codigoparallevar.minicards.types.wireData.WireDataType;
public class Wire<T extends WireDataType, InputConnectorType extends InputConnector<T, InputConnectorType>>
implements Moveable, Drawable {
implements Moveable, Drawable, Selectable {
private final double MAX_DISTANCE_TO_CONTAINS = 15;
private final Dropper _dropper;
private int _xinit;
private int _yinit;
private int _xend;
private int _yend;
private Path path = null;
private final static int _pathRunWay = 100;
protected InputConnectorType _attachedTo = null;
protected OutputConnector _attachedFrom = null;
@ -36,12 +41,14 @@ public class Wire<T extends WireDataType, InputConnectorType extends InputConnec
public void moveStart(int x, int y){
_xinit = x;
_yinit = y;
invalidatePath();
}
@Override
public void moveEnd(int x, int y) {
_xend = x;
_yend = y;
invalidatePath(); // Invalidate current path
}
@Override
@ -51,23 +58,17 @@ public class Wire<T extends WireDataType, InputConnectorType extends InputConnec
@Override
public void draw(ScrolledCanvas canvas, boolean devMode) {
final Path samplePath = new Path();
samplePath.moveTo(_xinit, _yinit);
samplePath.cubicTo(
_xinit, _yinit + _pathRunWay,
_xend, _yend - _pathRunWay,
_xend, _yend);
Paint pathPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
pathPaint.setColor(Color.parseColor("#44FF44"));
pathPaint.setStrokeWidth(10.0f);
pathPaint.setStrokeCap(Paint.Cap.ROUND);
pathPaint.setStyle(Paint.Style.STROKE);
canvas.drawPath(samplePath, pathPaint);
canvas.drawPath(getPath(), pathPaint);
}
public int getXEnd() {
return _xend;
}
@ -83,18 +84,94 @@ public class Wire<T extends WireDataType, InputConnectorType extends InputConnec
_xend = resultPoint.getX();
_yend = resultPoint.getY();
resultPoint.getAttachment(this);
invalidatePath();
}
public InputConnector getAttachedTo() {
return _attachedTo;
}
@Override
public Moveable getMoveable() {
return null;
}
public void unlink() {
_attachedTo = null;
_dropper.unlinkWire(this);
_attachedFrom.unlinkWire(this);
_attachedTo.unlinkWire(this);
}
public Object query(Object lastValue) {
return this._attachedFrom.query(lastValue);
}
private void invalidatePath() {
path = null;
}
private Path getPath() {
if (path == null) {
path = new Path();
// Bezier
path.moveTo(_xinit, _yinit);
path.cubicTo(
_xinit, _yinit + _pathRunWay,
_xend, _yend - _pathRunWay,
_xend, _yend);
}
return path;
}
@Override
public boolean containsPoint(int x, int y) {
return distanceToPoint(x, y) < MAX_DISTANCE_TO_CONTAINS;
}
private double distanceToPoint(int x, int y) {
final int POINT_HALFSIDE = 25 / 2;
RectF rectangle = new RectF(x - POINT_HALFSIDE, y - POINT_HALFSIDE,
x + POINT_HALFSIDE, y + POINT_HALFSIDE);
double sqDist1 = squareDistanceToSegment(_xinit, _yinit,
_xinit, _yinit + _pathRunWay / 3,
x, y
);
double sqDist2 = squareDistanceToSegment(
_xinit, _yinit + _pathRunWay / 3,
_xend, _yend - _pathRunWay / 3,
x, y
);
double sqDist3 = squareDistanceToSegment(
_xend, _yend - _pathRunWay / 3,
_xend, _yend,
x, y
);
return Math.sqrt(Math.min(sqDist1, Math.min(sqDist2, sqDist3)));
}
private double squareDistanceToSegment(int vx, int vy, int wx, int wy, int px, int py) {
// Return minimum distance between line segment vw and point p
// i.e. |w-v|^2 - avoid a sqrt
final double l2 = distance(vx, vy, wx, wy);
if (l2 == 0.0) return distance(vx, vy, px, py); // v == w case
// Consider the line extending the segment, parameterized as v + t (w - v).
// We find projection of point p onto the line.
// It falls where t = [(p-v) . (w-v)] / |w-v|^2
// We clamp t from [0,1] to handle points outside the segment vw.
double pointInLine = ((px - vx) * (wx - vx) + (py - vy) * (wy - vy)) / l2;
pointInLine = Math.max(0, Math.min(1, pointInLine));
return distance(vx + pointInLine * (wx - vx),
vy + pointInLine * (wy - vy),
px, py
);
}
private double distance(double vx, double vy, double px, double py) {
return Math.pow(vx - px, 2) + Math.pow(vy - py, 2);
}
}