Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.util.NavigableSet;
import java.util.Optional;
import java.util.TreeSet;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
Expand Down Expand Up @@ -157,7 +158,6 @@ protected boolean removeEldestEntry(Map.Entry<Path, TreeItem<Path>> eldest) {
@FXML private StackPane imagesStackPane;
@FXML private ImageView backgroundImageView; // The background image layer
@FXML private ImageView portraitImageView; // The bottom "Portrait" layer
@FXML private ImageView maskImageView; // The mask layer used to crop the Portrait layer
@FXML private ImageView overlayImageView; // The overlay layer to apply on top of everything
@FXML private ImageView tokenImageView; // The final token image created
@FXML private CheckBox useFileNumberingCheckbox;
Expand Down Expand Up @@ -192,6 +192,13 @@ protected boolean removeEldestEntry(Map.Entry<Path, TreeItem<Path>> eldest) {
@FXML private RadioMenuItem overlayMenuItem;
private FileSaveUtil fileSaveUtil = new FileSaveUtil();

/**
* The mask layer used to crop the Portrait layer.
*
* <p>This is not part of the main scene, but is used when compositing result images.
*/
private ImageView maskImageView;

// A custom set of Width/Height sizes to use for Overlays
private NavigableSet<Integer> overlaySpinnerSteps =
new TreeSet<>(
Expand Down Expand Up @@ -252,8 +259,6 @@ void initialize() {
: "fx:id=\"backgroundImageView\" was not injected: check your FXML file 'TokenTool.fxml'.";
assert portraitImageView != null
: "fx:id=\"portraitImageView\" was not injected: check your FXML file 'TokenTool.fxml'.";
assert maskImageView != null
: "fx:id=\"maskImageView\" was not injected: check your FXML file 'TokenTool.fxml'.";
assert overlayImageView != null
: "fx:id=\"overlayImageView\" was not injected: check your FXML file 'TokenTool.fxml'.";
assert tokenImageView != null
Expand Down Expand Up @@ -325,6 +330,20 @@ void initialize() {
assert overlayMenuItem != null
: "fx:id=\"overlayMenuItem\" was not injected: check your FXML file 'TokenTool.fxml'.";

var defaultImageUrl =
getClass().getResource("/net/rptools/tokentool/image/gear-chrome-mask.png");
maskImageView =
defaultImageUrl == null ? new ImageView() : new ImageView(defaultImageUrl.toExternalForm());
maskImageView.setVisible(true);
maskImageView.setId("maskImageView");
maskImageView.setFitWidth(256);
maskImageView.setFitHeight(256);
maskImageView.setLayoutX(1);
maskImageView.setLayoutY(1);
maskImageView.setMouseTransparent(true);
maskImageView.setPickOnBounds(true);
maskImageView.setPreserveRatio(true);

// We're getting the defaults set by the FXML before updating them with the saved preferences...
AppConstants.DEFAULT_MASK_IMAGE = maskImageView.getImage();
AppConstants.DEFAULT_OVERLAY_IMAGE = overlayImageView.getImage();
Expand Down Expand Up @@ -1232,17 +1251,29 @@ public void updateOverlayTreeview(TreeItem<Path> overlayTreeItems) {
}

public void updateTokenPreviewImageView() {
tokenImageView.setImage(
ImageUtil.composePreview(
compositeTokenPane,
backgroundImageView,
backgroundColorPicker.getValue(),
portraitImageView,
maskImageView,
overlayImageView,
overlayUseAsBaseCheckbox.isSelected(),
clipPortraitCheckbox.isSelected()));
tokenImageView.setPreserveRatio(true);
compositeTokenPane.layout();

boolean clip =
clipPortraitCheckbox.isSelected()
&& maskImageView.getFitWidth() > 0
&& maskImageView.getFitHeight() > 0;
CompletableFuture<? extends Image> future =
clip
? ImageUtil.Async.composeClippedPreview(
backgroundImageView,
backgroundColorPicker.getValue(),
portraitImageView,
maskImageView,
overlayImageView,
overlayUseAsBaseCheckbox.isSelected())
: ImageUtil.Async.composeUnclippedPreview(compositeTokenPane);
future
.thenCompose(i -> ImageUtil.Async.autoCrop(i))
.thenAccept(
cropped -> {
tokenImageView.setImage(cropped);
tokenImageView.setPreserveRatio(true);
});
}

private void saveToken() {
Expand Down
Loading
Loading