Commit 51e0378a authored by Benedikt Jensen's avatar Benedikt Jensen
Browse files

SkeletalAnimation2dEditor added

parent 57c55b9b
......@@ -9,7 +9,7 @@ void setup() {
}
void draw() {
for (int i = 0; i<600; i++) {
for (int i = 0; i<6; i++) {
float x = random(0,599);
float y = random(0,599);
if(dist(299.5,299.5,x,y)<299.5) {
......
void mouseMovement() {
PVector movement = new PVector(mouseX-lastMouseX, mouseY-lastMouseY);
lastMouseX = mouseX;
lastMouseY = mouseY;
mouseMovement = movement;
}
PVector mousePos() {
return new PVector(mouseX, mouseY);
}
void editorAction() {
// draw selectionBox
if (dragSelect) {
fill(255, 100);
stroke(255);
rect(dragFrom.x, dragFrom.y, mouseX-dragFrom.x, mouseY-dragFrom.y);
}
// MOVE selection
if (action == Action.MOVE && !selectedBones.isEmpty()) {
for (Bone bone : selectedBones) {
var counterRotation = bone.parent==null ? 0 : -bone.parent.getGlobalRot();
var transformedMouseMovement = mouseMovement.copy().rotate(counterRotation);
bone.pos.x += transformedMouseMovement.x;
bone.pos.y += transformedMouseMovement.y;
}
}
// SCALE selected vertices
if (action == Action.SCALE && !selectedBones.isEmpty()) {
for (Bone bone : selectedBones) {
PVector globalCenter = selectionCenterAnchor;
float originalDistance = dist(globalCenter.x, globalCenter.y, mouseAnchor.x, mouseAnchor.y);
float currentDistance = dist(globalCenter.x, globalCenter.y, mouseX, mouseY);
float rescaleValue = currentDistance / originalDistance;
bone.length = bone.lengthBeforeTransformation * rescaleValue;
//bone.pos.x = bone.beforeTransformation.x + (bone.beforeTransformation.x - centerOfTransform.x)*(mouseX-mouseAnchor.x-(mouseY-mouseAnchor.y))/100;
//bone.pos.y = bone.beforeTransformation.y + (bone.beforeTransformation.y - centerOfTransform.y)*(mouseX-mouseAnchor.x-(mouseY-mouseAnchor.y))/100;
}
}
// ROTATE selected vertices
if (action == Action.ROTATE && !selectedBones.isEmpty()) {
for (Bone bone : selectedBones) {
PVector relativeToCenter = PVector.sub(bone.posBeforeTransformation, centerOfTransform);
bone.rotation = originalRotation + (mouseX-mouseAnchor.x+mouseY-mouseAnchor.y)/100;
}
}
}
void select() {
Bone closestBone = null;
float shortestDistance = 9999f;
for (Bone bone : skeleton.bones) {
if (action != Action.NONE) return;
if (keyIsDown(CONTROL)) {
bone.unselect();
return;
}
PVector center = new PVector(0, -bone.length/3).rotate(bone.getGlobalRot()).add(bone.getGlobalPos());
var distance = dist(center.x, center.y, mouseX, mouseY);
if (distance < shortestDistance && distance < bone.length/2) {
shortestDistance = distance;
closestBone = bone;
} else {
//add/substract to selection
if (!keyIsDown(SHIFT))
bone.unselect();
}
}
if (closestBone != null) {
if (closestBone.isSelected) {
closestBone.unselect();
} else {
closestBone.select();
}
}
}
Bone createBone(Bone parent) {
var mousePos = mousePos();
Bone bone;
if (parent==null) {
bone = new Bone(null, mousePos.copy(), 0, 100f);
} else {
var endOfBone = parent.getEndOfBone();
var angle = getAngle(mousePos.copy().sub(endOfBone)) - parent.getGlobalRot();
bone = new Bone(
parent,
new PVector(0, 0),
angle,
endOfBone.copy().sub(mousePos).mag());
println("global_rot: " + bone.getGlobalRot());
println("end: " + parent.getEndOfBone());
println("rotation: " + parent.getGlobalRot());
}
skeleton.addBone(bone);
selectedBones.clear();
bone.select();
return bone;
}
PVector getCenter(ArrayList<Bone> bones) {
if (bones.size()==0) return new PVector(0, 0);
float minX = bones.get(0).pos.x;
float minY = bones.get(0).pos.y;
float maxX = bones.get(0).pos.x;
float maxY = bones.get(0).pos.y;
for (Bone bone : bones) {
if (bone.pos.x < minX) minX = bone.pos.x;
if (bone.pos.y < minY) minY = bone.pos.y;
if (bone.pos.x > maxX) maxX = bone.pos.x;
if (bone.pos.y > maxY) maxY = bone.pos.y;
}
PVector center = new PVector( (minX+maxX)/2, (minY+maxY)/2 );
return center;
}
float getAngle(PVector vector) {
if (vector.x>=0) {
return PVector.angleBetween(new PVector(0, -1), vector);
} else {
return PVector.angleBetween(new PVector(0, 1), vector) + PI;
}
}
float lastMouseX = mouseX;
float lastMouseY = mouseY;
float originalRotation;
PVector mouseAnchor = mousePos();
PVector selectionCenterAnchor = new PVector(0, 0);
PVector mouseMovement = new PVector();
PVector centerOfTransform;
PVector dragFrom;
boolean dragSelect = false;
Action action = Action.NONE;
enum Action {
ROTATE,
SCALE,
MOVE,
NONE,
}
ArrayList<Bone> selectedBones = new ArrayList<>();
Set<Integer> pressedKeys = new HashSet<Integer>();
void mousePressed() {
dragFrom = new PVector(mouseX, mouseY);
}
void mouseDragged() {
if (keyIsDown(CONTROL)) {
return;
}
if (action == Action.NONE) {
if (dist(dragFrom.x, dragFrom.y, mouseX, mouseY) > 10) {
dragSelect = true;
}
}
}
void mouseReleased() {
if (action != Action.NONE) {
action = Action.NONE;
} else if (dragSelect) {
dragSelect = false;
for (Bone bone : skeleton.bones) {
// If SHIFT isn't down unselect all
if (!keyIsDown(SHIFT)) {
bone.unselect();
}
// Select/Unselect bones inside rubber band
if (isInsideRect(bone.getGlobalPos(), dragFrom, new PVector(mouseX, mouseY))) {
if (bone.isSelected) bone.unselect();
else bone.select();
}
}
} else {
// If CONTROL is down create Bone
if (keyIsDown(CONTROL)) {
Bone parent = selectedBones.size() > 0 ?
selectedBones.get(selectedBones.size()-1) :
null;
Bone newBone = createBone(parent);
// Make only new bone selected
for (Bone bone : skeleton.bones) {
if (bone == newBone) {
bone.select();
} else {
bone.unselect();
}
}
} else {
select();
}
}
}
void setSelectionCenterAnchor() {
PVector topLeft = selectedBones.get(0).getGlobalPos().copy();
PVector bottomRight = topLeft.copy();
for (Bone bone : selectedBones) {
var boneGlobalPos = bone.getGlobalPos();
if (boneGlobalPos.x < topLeft.x) topLeft.x = boneGlobalPos.x;
if (boneGlobalPos.y < topLeft.y) topLeft.y = boneGlobalPos.y;
if (boneGlobalPos.x > bottomRight.x) bottomRight.x = boneGlobalPos.x;
if (boneGlobalPos.y > bottomRight.y) bottomRight.y = boneGlobalPos.y;
}
selectionCenterAnchor = topLeft.copy().add(bottomRight).div(2);
}
void keyPressed() {
setSelectionCenterAnchor();
//add keys to list of pressed keys
if (keyCode==SHIFT) pressedKeys.add(new Integer(SHIFT));
if (keyCode==CONTROL) pressedKeys.add(new Integer(CONTROL));
//move
if (key=='g') {
action = Action.MOVE;
}
//scale
if (key=='s') {
action = Action.SCALE;
centerOfTransform = getCenter(selectedBones);
mouseAnchor = mousePos();
for (Bone bone : selectedBones) {
bone.lengthBeforeTransformation = bone.length;
}
}
//rotate
if (key=='r') {
if (selectedBones.size()!=0) {
action = Action.ROTATE;
centerOfTransform = getCenter(selectedBones);
mouseAnchor = mousePos();
for (Bone bone : selectedBones) {
originalRotation = bone.rotation;
bone.posBeforeTransformation = bone.pos.copy();
}
}
}
//delete
if (key=='x') {
skeleton.bones.removeAll(selectedBones);
selectedBones.clear();
}
//add keyframe
if (key=='k') {
}
}
void keyReleased() {
//remove keys from list of pressed keys
if (keyCode==SHIFT) pressedKeys.remove(new Integer(SHIFT));
if (keyCode==CONTROL) pressedKeys.remove(new Integer(CONTROL));
}
boolean keyIsDown(int pressedKey) {
return pressedKeys.contains(pressedKey);
}
boolean isInsideRect(PVector v, PVector p1, PVector p2) {
if (v.x < p1.x && v.x < p2.x) return false;
if (v.x > p1.x && v.x > p2.x) return false;
if (v.y < p1.y && v.y < p2.y) return false;
if (v.y > p1.y && v.y > p2.y) return false;
return true;
}
import java.util.*;
color colorSelected = color(255, 255, 255);
color colorDefault = color(252, 186, 3);
Skeleton skeleton;
void setup() {
size(800, 600);
skeleton = new Skeleton();
skeleton
.addBone(new Bone(null, new PVector(400, 300), 0, 100));
}
void draw() {
background(100);
mouseMovement();
editorAction();
skeleton.display();
}
class Skeleton {
ArrayList<Bone> bones = new ArrayList<>();
ArrayList<Animation> animations = new ArrayList<>();
void display() {
for (var bone : bones) {
bone.display();
}
}
void addBone(Bone bone) {
bones.add(bone);
}
}
class Bone {
Bone parent;
PVector pos;
float rotation;
float length;
boolean isSelected = false;
PVector posBeforeTransformation;
float lengthBeforeTransformation;
Bone(Bone parent, PVector pos, float rotation, float length) {
this.parent = parent;
this.pos = pos;
this.rotation = rotation;
this.length = length;
}
void display() {
fill(isSelected ? colorSelected : colorDefault);
stroke(isSelected ? colorSelected : colorDefault);
pushMatrix();
var globalPos = getGlobalPos();
translate(globalPos.x, globalPos.y);
rotate(getGlobalRot());
line(0, 0, 0, -length);
line(0, 0, -0.1*length, 0.3*-length);
line(0, 0, 0.1*length, 0.3*-length);
line(-0.1*length, 0.3*-length, 0, -length);
line(0.1*length, 0.3*-length, 0, -length);
line(-0.1*length, 0.3*-length, 0.1*length, 0.3*-length);
rect(-2, -2, 4, 4);
rect(-2, -2-length, 4, 4);
popMatrix();
}
void select() {
isSelected = true;
if (!selectedBones.contains(this))
selectedBones.add(this);
}
void unselect() {
isSelected = false;
if (selectedBones.contains(this))
selectedBones.remove(this);
}
PVector getGlobalPos() {
if (parent==null) return pos.copy();
else {
return parent.getEndOfBone().add(pos.copy().rotate(parent.getGlobalRot()));
}
}
PVector getEndOfBone() {
PVector v = new PVector(0,-length).rotate(getGlobalRot());
return getGlobalPos().add(v);
}
float getGlobalRot() {
if (parent==null) return rotation;
else return rotation + parent.getGlobalRot();
}
}
class Animation {
HashMap<Bone, ArrayList<KeyFrame>> boneAnimations = new HashMap<>();
}
class KeyFrame {
float time;
PVector translation;
float rotation;
float scale;
KeyFrame(PVector translation, float rotation, float scale) {
this.translation = translation;
this.rotation = rotation;
this.scale = scale;
}
}
void setup() {
size(640,480);
}
void draw() {
background(50);
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment