Layer opacity (#312)

Closes #187

* Add layer opacity input

* Improve Rust code cleanliness
This commit is contained in:
Keavon Chambers
2021-07-27 23:15:23 -07:00
parent 12fc330952
commit 0cdd1762b8
9 changed files with 86 additions and 18 deletions

View File

@@ -1,11 +1,11 @@
<template>
<LayoutCol :class="'layer-tree-panel'">
<LayoutRow :class="'options-bar'">
<DropdownInput :menuEntries="blendModeEntries" v-model:selectedIndex="blendModeSelectedIndex" @update:selectedIndex="blendModeChanged" :disabled="blendModeDropdownDisabled" />
<DropdownInput v-model:selectedIndex="blendModeSelectedIndex" @update:selectedIndex="setLayerBlendMode" :menuEntries="blendModeEntries" :disabled="blendModeDropdownDisabled" />
<Separator :type="SeparatorType.Related" />
<NumberInput v-model:value="opacity" :min="0" :max="100" :unit="`%`" :displayDecimalPlaces="2" />
<NumberInput v-model:value="opacity" @update:value="setLayerOpacity" :min="0" :max="100" :unit="`%`" :displayDecimalPlaces="2" :disabled="opacityNumberInputDisabled" />
<Separator :type="SeparatorType.Related" />
@@ -179,9 +179,16 @@ export default defineComponent({
const { toggle_layer_visibility } = await wasm;
toggle_layer_visibility(path);
},
async setLayerBlendMode(blendMode: BlendMode) {
const { set_blend_mode_for_selected_layers } = await wasm;
set_blend_mode_for_selected_layers(blendMode);
async setLayerBlendMode() {
const blendMode = this.blendModeEntries.flat()[this.blendModeSelectedIndex].value as BlendMode;
if (blendMode) {
const { set_blend_mode_for_selected_layers } = await wasm;
set_blend_mode_for_selected_layers(blendMode);
}
},
async setLayerOpacity() {
const { set_opacity_for_selected_layers } = await wasm;
set_opacity_for_selected_layers(this.opacity);
},
async handleControlClick(clickedLayer: LayerPanelEntry) {
const index = this.layers.indexOf(clickedLayer);
@@ -199,7 +206,7 @@ export default defineComponent({
},
async handleShiftClick(clickedLayer: LayerPanelEntry) {
// The two paths of the range are stored in selectionRangeStartLayer and selectionRangeEndLayer
// So for a new Shift+Click, select all layers between selectionRangeStartLayer and selectionRangeEndLayer (stored in prev Shift+Click)
// So for a new Shift+Click, select all layers between selectionRangeStartLayer and selectionRangeEndLayer (stored in previous Shift+Click)
this.clearSelection();
this.selectionRangeEndLayer = clickedLayer;
@@ -276,12 +283,28 @@ export default defineComponent({
this.blendModeSelectedIndex = this.blendModeEntries.flat().findIndex((entry) => entry.value === firstEncounteredBlendMode);
} else {
// Display a dash when they are not all the same value
this.blendModeSelectedIndex = -1;
this.blendModeSelectedIndex = NaN;
}
},
blendModeChanged() {
const blendMode = this.blendModeEntries.flat()[this.blendModeSelectedIndex].value as BlendMode;
if (blendMode) this.setLayerBlendMode(blendMode);
setOpacityForSelectedLayers() {
const selected = this.layers.filter((layer) => layer.layer_data.selected);
if (selected.length < 1) {
this.opacity = 100;
this.opacityNumberInputDisabled = true;
return;
}
this.opacityNumberInputDisabled = false;
const firstEncounteredOpacity = selected[0].opacity;
const allOpacitiesAlike = !selected.find((layer) => layer.opacity !== firstEncounteredOpacity);
if (allOpacitiesAlike) {
this.opacity = firstEncounteredOpacity;
} else {
// Display a dash when they are not all the same value
this.opacity = NaN;
}
},
},
mounted() {
@@ -295,6 +318,7 @@ export default defineComponent({
this.layers = responseLayers;
this.setBlendModeForSelectedLayers();
this.setOpacityForSelectedLayers();
}
});
registerResponseHandler(ResponseType.CollapseFolder, (responseData) => {
@@ -306,6 +330,7 @@ export default defineComponent({
blendModeEntries,
blendModeSelectedIndex: 0,
blendModeDropdownDisabled: true,
opacityNumberInputDisabled: true,
layers: [] as Array<LayerPanelEntry>,
selectionRangeStartLayer: undefined as undefined | LayerPanelEntry,
selectionRangeEndLayer: undefined as undefined | LayerPanelEntry,

View File

@@ -244,10 +244,15 @@ function newBlendMode(input: string): BlendMode {
return blendMode;
}
function newOpacity(input: number): number {
return input * 100;
}
export interface LayerPanelEntry {
name: string;
visible: boolean;
blend_mode: BlendMode;
opacity: number;
layer_type: LayerType;
path: BigUint64Array;
layer_data: LayerData;
@@ -258,6 +263,7 @@ function newLayerPanelEntry(input: any): LayerPanelEntry {
name: input.name,
visible: input.visible,
blend_mode: newBlendMode(input.blend_mode),
opacity: newOpacity(input.opacity),
layer_type: newLayerType(input.layer_type),
layer_data: newLayerData(input.layer_data),
path: new BigUint64Array(input.path.map((n: number) => BigInt(n))),

View File

@@ -213,7 +213,7 @@ pub fn reorder_selected_layers(delta: i32) -> Result<(), JsValue> {
.map_err(convert_error)
}
/// Set the blend mode of the selected layers
/// Set the blend mode for the selected layers
#[wasm_bindgen]
pub fn set_blend_mode_for_selected_layers(blend_mode_svg_style_name: String) -> Result<(), JsValue> {
let blend_mode = match blend_mode_svg_style_name.as_str() {
@@ -239,6 +239,17 @@ pub fn set_blend_mode_for_selected_layers(blend_mode_svg_style_name: String) ->
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentMessage::SetBlendModeForSelectedLayers(blend_mode)).map_err(convert_error))
}
/// Set the opacity for the selected layers
#[wasm_bindgen]
pub fn set_opacity_for_selected_layers(opacity_percent: f64) -> Result<(), JsValue> {
EDITOR_STATE.with(|editor| {
editor
.borrow_mut()
.handle_message(DocumentMessage::SetOpacityForSelectedLayers(opacity_percent / 100.))
.map_err(convert_error)
})
}
/// Export the document
#[wasm_bindgen]
pub fn export_document() -> Result<(), JsValue> {