mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-16 23:08:05 +08:00
Layer opacity (#312)
Closes #187 * Add layer opacity input * Improve Rust code cleanliness
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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))),
|
||||
|
||||
@@ -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> {
|
||||
|
||||
Reference in New Issue
Block a user