1
0
mirror of https://github.com/aNNiMON/HotaruFX.git synced 2024-09-19 14:14:21 +03:00

Add group node

This commit is contained in:
Victor 2017-09-02 12:33:30 +03:00
parent 1c5adfe885
commit 502ad42fde
7 changed files with 99 additions and 5 deletions

View File

@ -3,13 +3,17 @@ package com.annimon.hotarufx.bundles;
import com.annimon.hotarufx.lib.Context;
import com.annimon.hotarufx.lib.Function;
import com.annimon.hotarufx.lib.NodeValue;
import com.annimon.hotarufx.lib.Types;
import com.annimon.hotarufx.lib.Validator;
import com.annimon.hotarufx.visual.objects.CircleNode;
import com.annimon.hotarufx.visual.objects.GroupNode;
import com.annimon.hotarufx.visual.objects.ObjectNode;
import com.annimon.hotarufx.visual.objects.RectangleNode;
import com.annimon.hotarufx.visual.objects.SVGPathNode;
import com.annimon.hotarufx.visual.objects.TextNode;
import java.util.Arrays;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import lombok.val;
public class NodesBundle implements Bundle {
@ -17,6 +21,7 @@ public class NodesBundle implements Bundle {
@Override
public void load(Context context) {
context.functions().put("circle", node(CircleNode::new));
context.functions().put("group", group());
context.functions().put("rectangle", node(RectangleNode::new));
context.functions().put("svgPath", node(SVGPathNode::new));
context.functions().put("text", node(TextNode::new));
@ -30,4 +35,14 @@ public class NodesBundle implements Bundle {
return node;
};
}
private Function group() {
return args -> {
val nodes = Arrays.stream(args)
.filter(v -> v.type() == Types.NODE)
.map(v -> ((NodeValue) v).getNode())
.collect(Collectors.toList());
return new NodeValue(new GroupNode(nodes));
};
}
}

View File

@ -61,7 +61,7 @@ public enum PropertyType {
private static Function<Value, Object> toClipNode() {
return v -> {
ObjectNode node = ((NodeValue) v).getNode();
node.setUsedAsClip(true);
node.setRenderable(false);
return node.getFxNode();
};
}

View File

@ -0,0 +1,62 @@
package com.annimon.hotarufx.visual.objects;
import com.annimon.hotarufx.visual.PropertyBindings;
import com.annimon.hotarufx.visual.PropertyTimeline;
import com.annimon.hotarufx.visual.PropertyTimelineHolder;
import com.annimon.hotarufx.visual.TimeLine;
import com.annimon.hotarufx.visual.visitors.NodeVisitor;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import javafx.scene.Group;
import lombok.val;
import static com.annimon.hotarufx.visual.PropertyType.BOOLEAN;
public class GroupNode extends ObjectNode {
public final Group group;
public final List<ObjectNode> nodes;
private PropertyTimelineHolder<Boolean> autoSizeChildren;
public GroupNode(List<ObjectNode> nodes) {
this(new Group(), nodes);
}
private GroupNode(Group group, List<ObjectNode> nodes) {
super(group);
this.group = group;
this.nodes = new ArrayList<>(nodes);
val fxNodes = nodes.stream()
.map(ObjectNode::getFxNode)
.collect(Collectors.toList());
group.getChildren().addAll(fxNodes);
autoSizeChildren = PropertyTimelineHolder.empty();
}
public PropertyTimeline<Boolean> autoSizeChildrenProperty() {
return autoSizeChildren.setIfEmptyThenGet(group::autoSizeChildrenProperty);
}
@Override
public void buildTimeline(TimeLine timeline) {
super.buildTimeline(timeline);
autoSizeChildren.applyIfPresent(timeline);
for (ObjectNode node : nodes) {
node.buildTimeline(timeline);
}
}
@Override
public PropertyBindings propertyBindings(PropertyBindings bindings) {
return super.propertyBindings(bindings)
.add("autoSize", BOOLEAN, this::autoSizeChildrenProperty)
.add("autoSizeChildren", BOOLEAN, this::autoSizeChildrenProperty);
}
@Override
public <R, T> R accept(NodeVisitor<R, T> visitor, T input) {
return visitor.visit(this, input);
}
}

View File

@ -22,7 +22,7 @@ public abstract class ObjectNode {
private PropertyTimelineHolder<Number> scaleX, scaleY, scaleZ;
private PropertyTimelineHolder<Number> layoutX, layoutY;
@Getter @Setter
private boolean isUsedAsClip;
private boolean isRenderable;
public ObjectNode(Node node) {
this.node = node;
@ -39,7 +39,7 @@ public abstract class ObjectNode {
scaleZ = PropertyTimelineHolder.empty();
layoutX = PropertyTimelineHolder.empty();
layoutY = PropertyTimelineHolder.empty();
isUsedAsClip = false;
isRenderable = true;
}
public Node getFxNode() {

View File

@ -1,6 +1,7 @@
package com.annimon.hotarufx.visual.visitors;
import com.annimon.hotarufx.visual.objects.CircleNode;
import com.annimon.hotarufx.visual.objects.GroupNode;
import com.annimon.hotarufx.visual.objects.RectangleNode;
import com.annimon.hotarufx.visual.objects.SVGPathNode;
import com.annimon.hotarufx.visual.objects.TextNode;
@ -8,6 +9,7 @@ import com.annimon.hotarufx.visual.objects.TextNode;
public interface NodeVisitor<R, T> {
R visit(CircleNode node, T input);
R visit(GroupNode node, T input);
R visit(RectangleNode node, T input);
R visit(SVGPathNode node, T input);
R visit(TextNode node, T input);

View File

@ -3,6 +3,7 @@ package com.annimon.hotarufx.visual.visitors;
import com.annimon.hotarufx.visual.TimeLine;
import com.annimon.hotarufx.visual.VirtualScene;
import com.annimon.hotarufx.visual.objects.CircleNode;
import com.annimon.hotarufx.visual.objects.GroupNode;
import com.annimon.hotarufx.visual.objects.ObjectNode;
import com.annimon.hotarufx.visual.objects.RectangleNode;
import com.annimon.hotarufx.visual.objects.SVGPathNode;
@ -19,6 +20,16 @@ public class RenderVisitor implements NodeVisitor<Void, VirtualScene> {
return render(node, scene);
}
@Override
public Void visit(GroupNode group, VirtualScene scene) {
render(group, scene);
for (ObjectNode node : group.nodes) {
node.setRenderable(false);
node.accept(this, scene);
}
return null;
}
@Override
public Void visit(RectangleNode node, VirtualScene scene) {
return render(node, scene);
@ -36,7 +47,7 @@ public class RenderVisitor implements NodeVisitor<Void, VirtualScene> {
private Void render(ObjectNode node, VirtualScene scene) {
node.buildTimeline(timeline);
if (!node.isUsedAsClip()) {
if (node.isRenderable()) {
scene.add(node.getFxNode());
}
return null;

View File

@ -71,4 +71,8 @@ HEART = svgPath({
stroke: "white"
})
render(B, A, C, CLIP, HEART)
#render(B, A, C, CLIP, HEART)
G1 = group(B, A)
G1@rotate.add(10, 45).add(20, -45)
render(G1)