Add removal mechanism for signal wires.
This commit is contained in:
parent
a2bcf79309
commit
8b3bbfee78
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user