Skip to content

Commit 6edfe96

Browse files
TomyLobome4502octylFractal
authored
Add clipboard support to //deform (#2276)
* Rename offset arguments on //deform, //generate and //generatebiome to offsetPlacement * More accurate comments * Give some variables more appropriate names * Add ScaleAndTranslateTransform class * Use ScaleAndTranslateTransform in WorldEditExpressionEnvironment * Use ScaleAndTranslateTransform in everything using WorldEditExpressionEnvironment * Add inputExtent parameter and separate in/outputTransform for deformRegion * Add clipboard support to //deform * Remove deprecated internal methods * Adjust JavaDoc to make it not seem specific to //deform * Add @deprecated links to newly @deprecated methods * Add JavaDoc to EditSession#makeBiomeShape * Update worldedit-core/src/main/java/com/sk89q/worldedit/regions/shape/WorldEditExpressionEnvironment.java Co-authored-by: Octavia Togami <octavia.togami@gmail.com> * Fix compile errors --------- Co-authored-by: Maddy Miller <git@madelinemiller.dev> Co-authored-by: Octavia Togami <octavia.togami@gmail.com>
1 parent 79b0da5 commit 6edfe96

8 files changed

Lines changed: 380 additions & 145 deletions

File tree

worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java

Lines changed: 151 additions & 21 deletions
Large diffs are not rendered by default.

worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java

Lines changed: 8 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@
3232
import com.sk89q.worldedit.internal.annotation.Radii;
3333
import com.sk89q.worldedit.internal.annotation.Selection;
3434
import com.sk89q.worldedit.internal.expression.ExpressionException;
35+
import com.sk89q.worldedit.internal.util.TransformUtil;
3536
import com.sk89q.worldedit.math.BlockVector3;
36-
import com.sk89q.worldedit.math.Vector3;
37+
import com.sk89q.worldedit.math.transform.Transform;
3738
import com.sk89q.worldedit.regions.Region;
3839
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
3940
import com.sk89q.worldedit.util.formatting.text.TextComponent;
@@ -370,45 +371,13 @@ public int generate(Actor actor, LocalSession session, EditSession editSession,
370371
@Switch(name = 'r', desc = "Use the game's coordinate origin")
371372
boolean useRawCoords,
372373
@Switch(name = 'o', desc = "Use the placement's coordinate origin")
373-
boolean offset,
374+
boolean offsetPlacement,
374375
@Switch(name = 'c', desc = "Use the selection's center as origin")
375376
boolean offsetCenter) throws WorldEditException {
376-
377-
final Vector3 zero;
378-
Vector3 unit;
379-
380-
if (useRawCoords) {
381-
zero = Vector3.ZERO;
382-
unit = Vector3.ONE;
383-
} else if (offset) {
384-
zero = session.getPlacementPosition(actor).toVector3();
385-
unit = Vector3.ONE;
386-
} else if (offsetCenter) {
387-
final Vector3 min = region.getMinimumPoint().toVector3();
388-
final Vector3 max = region.getMaximumPoint().toVector3();
389-
390-
zero = max.add(min).multiply(0.5);
391-
unit = Vector3.ONE;
392-
} else {
393-
final Vector3 min = region.getMinimumPoint().toVector3();
394-
final Vector3 max = region.getMaximumPoint().toVector3();
395-
396-
zero = max.add(min).multiply(0.5);
397-
unit = max.subtract(zero);
398-
399-
if (unit.x() == 0) {
400-
unit = unit.withX(1.0);
401-
}
402-
if (unit.y() == 0) {
403-
unit = unit.withY(1.0);
404-
}
405-
if (unit.z() == 0) {
406-
unit = unit.withZ(1.0);
407-
}
408-
}
377+
final Transform transform = TransformUtil.createTransformForExpressionCommand(actor, session, region, useRawCoords, offsetPlacement, offsetCenter);
409378

410379
try {
411-
final int affected = editSession.makeShape(region, zero, unit, pattern, String.join(" ", expression), hollow, session.getTimeout());
380+
final int affected = editSession.makeShape(region, transform, pattern, String.join(" ", expression), hollow, session.getTimeout());
412381
if (actor instanceof Player) {
413382
((Player) actor).findFreePosition();
414383
}
@@ -439,44 +408,13 @@ public int generateBiome(Actor actor, LocalSession session, EditSession editSess
439408
@Switch(name = 'r', desc = "Use the game's coordinate origin")
440409
boolean useRawCoords,
441410
@Switch(name = 'o', desc = "Use the placement's coordinate origin")
442-
boolean offset,
411+
boolean offsetPlacement,
443412
@Switch(name = 'c', desc = "Use the selection's center as origin")
444413
boolean offsetCenter) throws WorldEditException {
445-
final Vector3 zero;
446-
Vector3 unit;
447-
448-
if (useRawCoords) {
449-
zero = Vector3.ZERO;
450-
unit = Vector3.ONE;
451-
} else if (offset) {
452-
zero = session.getPlacementPosition(actor).toVector3();
453-
unit = Vector3.ONE;
454-
} else if (offsetCenter) {
455-
final Vector3 min = region.getMinimumPoint().toVector3();
456-
final Vector3 max = region.getMaximumPoint().toVector3();
457-
458-
zero = max.add(min).multiply(0.5);
459-
unit = Vector3.ONE;
460-
} else {
461-
final Vector3 min = region.getMinimumPoint().toVector3();
462-
final Vector3 max = region.getMaximumPoint().toVector3();
463-
464-
zero = max.add(min).multiply(0.5);
465-
unit = max.subtract(zero);
466-
467-
if (unit.x() == 0) {
468-
unit = unit.withX(1.0);
469-
}
470-
if (unit.y() == 0) {
471-
unit = unit.withY(1.0);
472-
}
473-
if (unit.z() == 0) {
474-
unit = unit.withZ(1.0);
475-
}
476-
}
414+
final Transform transform = TransformUtil.createTransformForExpressionCommand(actor, session, region, useRawCoords, offsetPlacement, offsetCenter);
477415

478416
try {
479-
final int affected = editSession.makeBiomeShape(region, zero, unit, target, String.join(" ", expression), hollow, session.getTimeout());
417+
final int affected = editSession.makeBiomeShape(region, transform, target, String.join(" ", expression), hollow, session.getTimeout());
480418
actor.printInfo(TranslatableComponent.of("worldedit.generatebiome.changed", TextComponent.of(affected)));
481419
return affected;
482420
} catch (ExpressionException e) {

worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@
3131
import com.sk89q.worldedit.entity.Player;
3232
import com.sk89q.worldedit.extension.platform.Actor;
3333
import com.sk89q.worldedit.extent.Extent;
34+
import com.sk89q.worldedit.extent.InputExtent;
3435
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
36+
import com.sk89q.worldedit.extent.clipboard.Clipboard;
3537
import com.sk89q.worldedit.function.GroundFunction;
3638
import com.sk89q.worldedit.function.RegionFunction;
3739
import com.sk89q.worldedit.function.RegionMaskingFilter;
@@ -49,13 +51,15 @@
4951
import com.sk89q.worldedit.internal.annotation.Offset;
5052
import com.sk89q.worldedit.internal.annotation.Selection;
5153
import com.sk89q.worldedit.internal.expression.ExpressionException;
54+
import com.sk89q.worldedit.internal.util.TransformUtil;
5255
import com.sk89q.worldedit.math.BlockVector3;
5356
import com.sk89q.worldedit.math.Vector3;
5457
import com.sk89q.worldedit.math.convolution.GaussianKernel;
5558
import com.sk89q.worldedit.math.convolution.HeightMap;
5659
import com.sk89q.worldedit.math.convolution.HeightMapFilter;
5760
import com.sk89q.worldedit.math.convolution.SnowHeightMap;
5861
import com.sk89q.worldedit.math.noise.RandomNoise;
62+
import com.sk89q.worldedit.math.transform.Transform;
5963
import com.sk89q.worldedit.regions.ConvexPolyhedralRegion;
6064
import com.sk89q.worldedit.regions.CuboidRegion;
6165
import com.sk89q.worldedit.regions.Region;
@@ -498,44 +502,30 @@ public int deform(Actor actor, LocalSession session, EditSession editSession,
498502
@Switch(name = 'r', desc = "Use the game's coordinate origin")
499503
boolean useRawCoords,
500504
@Switch(name = 'o', desc = "Use the placement's coordinate origin")
501-
boolean offset,
505+
boolean offsetPlacement,
502506
@Switch(name = 'c', desc = "Use the selection's center as origin")
503-
boolean offsetCenter) throws WorldEditException {
504-
final Vector3 zero;
505-
Vector3 unit;
506-
507-
if (useRawCoords) {
508-
zero = Vector3.ZERO;
509-
unit = Vector3.ONE;
510-
} else if (offset) {
511-
zero = session.getPlacementPosition(actor).toVector3();
512-
unit = Vector3.ONE;
513-
} else if (offsetCenter) {
514-
final Vector3 min = region.getMinimumPoint().toVector3();
515-
final Vector3 max = region.getMaximumPoint().toVector3();
516-
517-
zero = max.add(min).multiply(0.5);
518-
unit = Vector3.ONE;
519-
} else {
520-
final Vector3 min = region.getMinimumPoint().toVector3();
521-
final Vector3 max = region.getMaximumPoint().toVector3();
507+
boolean offsetCenter,
508+
@Switch(name = 'l', desc = "Fetch from the clipboard instead of the world")
509+
boolean useClipboard) throws WorldEditException {
510+
final Transform targetTransform = TransformUtil.createTransformForExpressionCommand(actor, session, region, useRawCoords, offsetPlacement, offsetCenter);
522511

523-
zero = max.add(min).divide(2);
524-
unit = max.subtract(zero);
512+
final InputExtent sourceExtent;
513+
final Transform sourceTransform;
514+
if (useClipboard) {
515+
final Clipboard clipboard = session.getClipboard().getClipboard();
516+
sourceExtent = clipboard;
525517

526-
if (unit.x() == 0) {
527-
unit = unit.withX(1.0);
528-
}
529-
if (unit.y() == 0) {
530-
unit = unit.withY(1.0);
531-
}
532-
if (unit.z() == 0) {
533-
unit = unit.withZ(1.0);
534-
}
518+
final Vector3 clipboardMin = clipboard.getMinimumPoint().toVector3();
519+
final Vector3 clipboardMax = clipboard.getMaximumPoint().toVector3();
520+
521+
sourceTransform = TransformUtil.createTransformForExpressionCommand(useRawCoords, offsetPlacement, offsetCenter, clipboardMin, clipboardMax, clipboardMin);
522+
} else {
523+
sourceExtent = editSession.getWorld();
524+
sourceTransform = targetTransform;
535525
}
536526

537527
try {
538-
final int affected = editSession.deformRegion(region, zero, unit, String.join(" ", expression), session.getTimeout());
528+
final int affected = editSession.deformRegion(region, targetTransform, String.join(" ", expression), session.getTimeout(), sourceExtent, sourceTransform);
539529
if (actor instanceof Player) {
540530
((Player) actor).findFreePosition();
541531
}

worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/ExpressionMaskParser.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import com.sk89q.worldedit.internal.expression.Expression;
2828
import com.sk89q.worldedit.internal.expression.ExpressionException;
2929
import com.sk89q.worldedit.internal.registry.InputParser;
30-
import com.sk89q.worldedit.math.Vector3;
30+
import com.sk89q.worldedit.math.transform.Identity;
3131
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
3232
import com.sk89q.worldedit.session.SessionOwner;
3333
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
@@ -58,7 +58,7 @@ public Mask parseFromInput(String input, ParserContext context) throws InputPars
5858
try {
5959
Expression exp = Expression.compile(input.substring(1), "x", "y", "z");
6060
WorldEditExpressionEnvironment env = new WorldEditExpressionEnvironment(
61-
context.requireExtent(), Vector3.ONE, Vector3.ZERO);
61+
context.requireExtent(), new Identity());
6262
exp.setEnvironment(env);
6363
if (context.getActor() != null) {
6464
SessionOwner owner = context.getActor();

worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
import com.sk89q.worldedit.internal.expression.Expression;
3434
import com.sk89q.worldedit.internal.expression.ExpressionException;
3535
import com.sk89q.worldedit.math.Vector3;
36+
import com.sk89q.worldedit.math.transform.Identity;
37+
import com.sk89q.worldedit.math.transform.ScaleAndTranslateTransform;
38+
import com.sk89q.worldedit.math.transform.Transform;
3639
import com.sk89q.worldedit.regions.NullRegion;
3740
import com.sk89q.worldedit.regions.Region;
3841
import com.sk89q.worldedit.util.formatting.text.Component;
@@ -118,18 +121,16 @@ public String toString() {
118121

119122
@Override
120123
public Operation createFromContext(final EditContext context) {
121-
final Vector3 zero;
122-
Vector3 unit;
123124

124125
Region region = firstNonNull(context.getRegion(), this.region);
125126

127+
final Transform transform;
126128
switch (mode) {
127129
case UNIT_CUBE:
128130
final Vector3 min = region.getMinimumPoint().toVector3();
129131
final Vector3 max = region.getMaximumPoint().toVector3();
130-
131-
zero = max.add(min).multiply(0.5);
132-
unit = max.subtract(zero);
132+
final Vector3 zero = max.add(min).multiply(0.5);
133+
Vector3 unit = max.subtract(zero);
133134

134135
if (unit.x() == 0) {
135136
unit = unit.withX(1.0);
@@ -140,35 +141,37 @@ public Operation createFromContext(final EditContext context) {
140141
if (unit.z() == 0) {
141142
unit = unit.withZ(1.0);
142143
}
144+
145+
transform = new ScaleAndTranslateTransform(zero, unit);
143146
break;
147+
144148
case RAW_COORD:
145-
zero = Vector3.ZERO;
146-
unit = Vector3.ONE;
149+
transform = new Identity();
147150
break;
151+
148152
case OFFSET:
149153
default:
150-
zero = offset;
151-
unit = Vector3.ONE;
154+
transform = new ScaleAndTranslateTransform(offset, Vector3.ONE);
155+
break;
152156
}
153-
154157
LocalSession session = context.getSession();
155-
return new DeformOperation(context.getDestination(), region, zero, unit, expression,
158+
return new DeformOperation(context.getDestination(), region, transform, expression,
156159
session == null ? WorldEdit.getInstance().getConfiguration().calculationTimeout : session.getTimeout());
157160
}
158161

159162
private record DeformOperation(
160163
Extent destination,
161164
Region region,
162-
Vector3 zero,
163-
Vector3 unit,
165+
Transform transform,
164166
Expression expression,
165167
int timeout
166168
) implements Operation {
167169
@Override
168170
public Operation resume(RunContext run) throws WorldEditException {
169171
try {
170172
// TODO: Move deformation code
171-
((EditSession) destination).deformRegion(region, zero, unit, expression, timeout);
173+
final EditSession editSession = (EditSession) destination;
174+
editSession.deformRegion(region, transform, expression, timeout, editSession.getWorld(), transform);
172175
return null;
173176
} catch (ExpressionException e) {
174177
throw new RuntimeException("Failed to execute expression", e); // TODO: Better exception to throw here?
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* WorldEdit, a Minecraft world manipulation toolkit
3+
* Copyright (C) sk89q <http://www.sk89q.com>
4+
* Copyright (C) WorldEdit team and contributors
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
*/
19+
20+
package com.sk89q.worldedit.internal.util;
21+
22+
import com.sk89q.worldedit.IncompleteRegionException;
23+
import com.sk89q.worldedit.LocalSession;
24+
import com.sk89q.worldedit.extension.platform.Actor;
25+
import com.sk89q.worldedit.math.Vector3;
26+
import com.sk89q.worldedit.math.transform.Identity;
27+
import com.sk89q.worldedit.math.transform.ScaleAndTranslateTransform;
28+
import com.sk89q.worldedit.math.transform.Transform;
29+
import com.sk89q.worldedit.regions.Region;
30+
31+
/**
32+
* Various internal utility methods related to {@link Transform}s.
33+
*/
34+
public final class TransformUtil {
35+
36+
private TransformUtil() {
37+
}
38+
39+
/**
40+
* Creates a {@link Transform} for various expression commands.
41+
*
42+
* @param actor Actor that ran the command
43+
* @param session Session that the command was run in
44+
* @param region Selection that the command was run in
45+
* @param useRawCoords Use the game's coordinate origin
46+
* @param offsetPlacement Use the placement's coordinate origin
47+
* @param offsetCenter Use the selection's center as origin
48+
* @return A transform from the expression coordinate system to the raw coordinate system
49+
*/
50+
public static Transform createTransformForExpressionCommand(Actor actor, LocalSession session, Region region, boolean useRawCoords, boolean offsetPlacement, boolean offsetCenter) throws IncompleteRegionException {
51+
final Vector3 placement = session.getPlacementPosition(actor).toVector3();
52+
final Vector3 min = region.getMinimumPoint().toVector3();
53+
final Vector3 max = region.getMaximumPoint().toVector3();
54+
55+
return createTransformForExpressionCommand(useRawCoords, offsetPlacement, offsetCenter, min, max, placement);
56+
}
57+
58+
/**
59+
* Creates a {@link Transform} for various expression commands from raw min/max/placement values.
60+
*
61+
* @param useRawCoords Use the game's coordinate origin
62+
* @param offsetPlacement Use the placement's coordinate origin
63+
* @param offsetCenter Use the selection's center as origin
64+
* @param min Minimum of the selection/clipboard
65+
* @param max Maximum of the selection/clipboard
66+
* @param placement Placement position
67+
* @return A transform from the expression coordinate system to the world/clipboard coordinate system
68+
*/
69+
public static Transform createTransformForExpressionCommand(boolean useRawCoords, boolean offsetPlacement, boolean offsetCenter, Vector3 min, Vector3 max, Vector3 placement) {
70+
if (useRawCoords) {
71+
return new Identity();
72+
}
73+
74+
if (offsetPlacement) {
75+
return new ScaleAndTranslateTransform(placement, Vector3.ONE);
76+
}
77+
78+
final Vector3 center = max.add(min).multiply(0.5);
79+
80+
if (offsetCenter) {
81+
return new ScaleAndTranslateTransform(center, Vector3.ONE);
82+
}
83+
84+
Vector3 scale = max.subtract(center);
85+
86+
if (scale.x() == 0) {
87+
scale = scale.withX(1.0);
88+
}
89+
if (scale.y() == 0) {
90+
scale = scale.withY(1.0);
91+
}
92+
if (scale.z() == 0) {
93+
scale = scale.withZ(1.0);
94+
}
95+
return new ScaleAndTranslateTransform(center, scale);
96+
}
97+
}

0 commit comments

Comments
 (0)