diff --git a/src/mol-geo/geometry/marker-data.ts b/src/mol-geo/geometry/marker-data.ts index 4112a80cf7537de07e5423660f2e87d6c85f0702..71a375db9fdaaa499761eab4d2757ddfab11d88f 100644 --- a/src/mol-geo/geometry/marker-data.ts +++ b/src/mol-geo/geometry/marker-data.ts @@ -9,8 +9,10 @@ import { Vec2 } from '../../mol-math/linear-algebra'; import { TextureImage, createTextureImage } from '../../mol-gl/renderable/util'; export type MarkerData = { + uMarker: ValueCell<number>, tMarker: ValueCell<TextureImage<Uint8Array>> uMarkerTexDim: ValueCell<Vec2> + dMarkerType: ValueCell<string>, markerAverage: ValueCell<number> markerStatus: ValueCell<number> } @@ -19,7 +21,7 @@ export function getMarkersAverage(array: Uint8Array, count: number): number { if (count === 0) return 0; let sum = 0; for (let i = 0; i < count; ++i) { - if (array[i]) sum += 1; + sum += +!!array[i]; } return sum / count; } @@ -29,17 +31,21 @@ export function createMarkers(count: number, markerData?: MarkerData): MarkerDat const average = getMarkersAverage(markers.array, count); const status = average === 0 ? 0 : -1; if (markerData) { + ValueCell.updateIfChanged(markerData.uMarker, 0); ValueCell.update(markerData.tMarker, markers); ValueCell.update(markerData.uMarkerTexDim, Vec2.create(markers.width, markers.height)); + ValueCell.updateIfChanged(markerData.dMarkerType, status === -1 ? 'groupInstance' : 'uniform'); ValueCell.updateIfChanged(markerData.markerAverage, average); ValueCell.updateIfChanged(markerData.markerStatus, status); return markerData; } else { return { + uMarker: ValueCell.create(0), tMarker: ValueCell.create(markers), uMarkerTexDim: ValueCell.create(Vec2.create(markers.width, markers.height)), markerAverage: ValueCell.create(average), markerStatus: ValueCell.create(status), + dMarkerType: ValueCell.create('uniform'), }; } } @@ -47,17 +53,21 @@ export function createMarkers(count: number, markerData?: MarkerData): MarkerDat const emptyMarkerTexture = { array: new Uint8Array(1), width: 1, height: 1 }; export function createEmptyMarkers(markerData?: MarkerData): MarkerData { if (markerData) { + ValueCell.updateIfChanged(markerData.uMarker, 0); ValueCell.update(markerData.tMarker, emptyMarkerTexture); ValueCell.update(markerData.uMarkerTexDim, Vec2.create(1, 1)); + ValueCell.updateIfChanged(markerData.dMarkerType, 'uniform'); ValueCell.updateIfChanged(markerData.markerAverage, 0); ValueCell.updateIfChanged(markerData.markerStatus, 0); return markerData; } else { return { + uMarker: ValueCell.create(0), tMarker: ValueCell.create(emptyMarkerTexture), uMarkerTexDim: ValueCell.create(Vec2.create(1, 1)), markerAverage: ValueCell.create(0), markerStatus: ValueCell.create(0), + dMarkerType: ValueCell.create('uniform'), }; } } \ No newline at end of file diff --git a/src/mol-gl/renderable/schema.ts b/src/mol-gl/renderable/schema.ts index 9d869d04b6d7a9d97be801e2a3b6488ae22c7aa6..c51013285ce70345ff73e68be34adccdb1c0384a 100644 --- a/src/mol-gl/renderable/schema.ts +++ b/src/mol-gl/renderable/schema.ts @@ -210,8 +210,10 @@ export type SizeSchema = typeof SizeSchema export type SizeValues = Values<SizeSchema> export const MarkerSchema = { + uMarker: UniformSpec('f', 'material'), uMarkerTexDim: UniformSpec('v2'), tMarker: TextureSpec('image-uint8', 'alpha', 'ubyte', 'nearest'), + dMarkerType: DefineSpec('string', ['uniform', 'groupInstance']), markerAverage: ValueSpec('number'), markerStatus: ValueSpec('number'), } as const; diff --git a/src/mol-gl/shader/chunks/apply-marker-color.glsl.ts b/src/mol-gl/shader/chunks/apply-marker-color.glsl.ts index 53291a3a4cbceb9716e56f9668da1500459147f3..9b888c7493cab936e2fddc26a84258b3efe49482 100644 --- a/src/mol-gl/shader/chunks/apply-marker-color.glsl.ts +++ b/src/mol-gl/shader/chunks/apply-marker-color.glsl.ts @@ -1,5 +1,4 @@ export const apply_marker_color = ` -float marker = floor(vMarker * 255.0 + 0.5); // rounding required to work on some cards on win if (marker > 0.1) { if (intMod(marker, 2.0) > 0.1) { gl_FragColor.rgb = mix(gl_FragColor.rgb, uHighlightColor, uHighlightStrength); diff --git a/src/mol-gl/shader/chunks/assign-marker-varying.glsl.ts b/src/mol-gl/shader/chunks/assign-marker-varying.glsl.ts index 0608fca27d3a38e6fbb785ea8e64e1588671adad..22442c2da62b8cb9a732a0a1ebf52b0528821300 100644 --- a/src/mol-gl/shader/chunks/assign-marker-varying.glsl.ts +++ b/src/mol-gl/shader/chunks/assign-marker-varying.glsl.ts @@ -1,3 +1,5 @@ export const assign_marker_varying = ` -vMarker = readFromTexture(tMarker, aInstance * float(uGroupCount) + group, uMarkerTexDim).a; +#if defined(dMarkerType_groupInstance) + vMarker = readFromTexture(tMarker, aInstance * float(uGroupCount) + group, uMarkerTexDim).a; +#endif `; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/assign-material-color.glsl.ts b/src/mol-gl/shader/chunks/assign-material-color.glsl.ts index aac6bc42f0f68c2aff9fe726c0a8f752161f3cf7..55b3c43443eee149007e3c9ff2628cfaef6af2cd 100644 --- a/src/mol-gl/shader/chunks/assign-material-color.glsl.ts +++ b/src/mol-gl/shader/chunks/assign-material-color.glsl.ts @@ -1,4 +1,13 @@ export const assign_material_color = ` +#if defined(dRenderVariant_color) || defined(dRenderVariant_marking) + #if defined(dMarkerType_uniform) + float marker = uMarker; + #elif defined(dMarkerType_groupInstance) + float marker = vMarker; + #endif + marker = floor(marker * 255.0 + 0.5); // rounding required to work on some cards on win +#endif + #if defined(dRenderVariant_color) #if defined(dUsePalette) vec4 material = vec4(texture2D(tPalette, vec2(vPaletteV, 0.5)).rgb, uAlpha); @@ -21,7 +30,7 @@ export const assign_material_color = ` vec4 material = packDepthToRGBA(gl_FragCoord.z); #endif #elif defined(dRenderVariant_markingDepth) - if (vMarker > 0.0) + if (marker > 0.0) discard; #ifdef enabledFragDepth vec4 material = packDepthToRGBA(gl_FragDepthEXT); @@ -29,13 +38,13 @@ export const assign_material_color = ` vec4 material = packDepthToRGBA(gl_FragCoord.z); #endif #elif defined(dRenderVariant_markingMask) - if (vMarker == 0.0) + if (marker == 0.0) discard; float depthTest = 1.0; if (uMarkingDepthTest) { depthTest = (fragmentDepth >= getDepth(gl_FragCoord.xy / uDrawingBufferSize)) ? 1.0 : 0.0; } - bool isHighlight = intMod(floor(vMarker * 255.0 + 0.5), 2.0) > 0.1; + bool isHighlight = intMod(marker, 2.0) > 0.1; vec4 material = vec4(0.0, depthTest, isHighlight ? 1.0 : 0.0, 1.0); #endif diff --git a/src/mol-gl/shader/chunks/common-frag-params.glsl.ts b/src/mol-gl/shader/chunks/common-frag-params.glsl.ts index 380fcf2a0cdb1f45b9fc0e8ff4b029174ad12975..e3aac5f0e61d0a1740385f21a90a9beaabc95a2e 100644 --- a/src/mol-gl/shader/chunks/common-frag-params.glsl.ts +++ b/src/mol-gl/shader/chunks/common-frag-params.glsl.ts @@ -23,10 +23,15 @@ uniform vec3 uHighlightColor; uniform vec3 uSelectColor; uniform float uHighlightStrength; uniform float uSelectStrength; -#if __VERSION__ == 100 - varying float vMarker; -#else - flat in float vMarker; + +#if defined(dMarkerType_uniform) + uniform float uMarker; +#elif defined(dMarkerType_groupInstance) + #if __VERSION__ == 100 + varying float vMarker; + #else + flat in float vMarker; + #endif #endif varying vec3 vModelPosition; diff --git a/src/mol-gl/shader/chunks/common-vert-params.glsl.ts b/src/mol-gl/shader/chunks/common-vert-params.glsl.ts index 8aaa7f39a3ff6a5b296b4503969debff1e08e03e..87bc9792286756131946134dc94ef6a413694f59 100644 --- a/src/mol-gl/shader/chunks/common-vert-params.glsl.ts +++ b/src/mol-gl/shader/chunks/common-vert-params.glsl.ts @@ -26,12 +26,16 @@ uniform vec4 uInvariantBoundingSphere; #endif #endif -uniform vec2 uMarkerTexDim; -uniform sampler2D tMarker; -#if __VERSION__ == 100 - varying float vMarker; -#else - flat out float vMarker; +#if defined(dMarkerType_uniform) + uniform float uMarker; +#elif defined(dMarkerType_groupInstance) + uniform vec2 uMarkerTexDim; + uniform sampler2D tMarker; + #if __VERSION__ == 100 + varying float vMarker; + #else + flat out float vMarker; + #endif #endif varying vec3 vModelPosition; diff --git a/src/mol-gl/shader/direct-volume.frag.ts b/src/mol-gl/shader/direct-volume.frag.ts index fe59807de0e9b5b468d1459329b79fcf20ef89db..6611631063258c21475ccd630f82e8304c33f409 100644 --- a/src/mol-gl/shader/direct-volume.frag.ts +++ b/src/mol-gl/shader/direct-volume.frag.ts @@ -55,8 +55,13 @@ uniform vec3 uHighlightColor; uniform vec3 uSelectColor; uniform float uHighlightStrength; uniform float uSelectStrength; -uniform vec2 uMarkerTexDim; -uniform sampler2D tMarker; + +#if defined(dMarkerType_uniform) + uniform float uMarker; +#elif defined(dMarkerType_groupInstance) + uniform vec2 uMarkerTexDim; + uniform sampler2D tMarker; +#endif uniform float uFogNear; uniform float uFogFar; @@ -329,7 +334,12 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 rayDir) { #include apply_light_color #endif - float vMarker = readFromTexture(tMarker, vInstance * float(uGroupCount) + group, uMarkerTexDim).a; + #if defined(dMarkerType_uniform) + float marker = uMarker; + #elif defined(dMarkerType_groupInstance) + float marker = readFromTexture(tMarker, vInstance * float(uGroupCount) + group, uMarkerTexDim).a; + marker = floor(marker * 255.0 + 0.5); // rounding required to work on some cards on win + #endif #include apply_interior_color #include apply_marker_color @@ -392,14 +402,18 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 rayDir) { gl_FragColor.a = material.a * uAlpha * uTransferScale; - #ifdef dPackedGroup - float group = decodeFloatRGB(textureGroup(floor(unitPos * uGridDim + 0.5) / uGridDim).rgb); - #else - vec3 g = floor(unitPos * uGridDim + 0.5); - float group = g.z + g.y * uGridDim.z + g.x * uGridDim.z * uGridDim.y; + #if defined(dMarkerType_uniform) + float marker = uMarker; + #elif defined(dMarkerType_groupInstance) + #ifdef dPackedGroup + float group = decodeFloatRGB(textureGroup(floor(unitPos * uGridDim + 0.5) / uGridDim).rgb); + #else + vec3 g = floor(unitPos * uGridDim + 0.5); + float group = g.z + g.y * uGridDim.z + g.x * uGridDim.z * uGridDim.y; + #endif + float marker = readFromTexture(tMarker, vInstance * float(uGroupCount) + group, uMarkerTexDim).a; + marker = floor(marker * 255.0 + 0.5); // rounding required to work on some cards on win #endif - - float vMarker = readFromTexture(tMarker, vInstance * float(uGroupCount) + group, uMarkerTexDim).a; #include apply_marker_color preFogAlphaBlended = (1.0 - preFogAlphaBlended) * gl_FragColor.a + preFogAlphaBlended; diff --git a/src/mol-gl/shader/image.frag.ts b/src/mol-gl/shader/image.frag.ts index bf6ec069218114e4e259acfb2ec9aa7288ef9cce..175c65fd933e96ee6334a8dc2b06b080dc1af9ae 100644 --- a/src/mol-gl/shader/image.frag.ts +++ b/src/mol-gl/shader/image.frag.ts @@ -116,20 +116,25 @@ void main() { discard; gl_FragColor = packDepthToRGBA(gl_FragCoord.z); #elif defined(dRenderVariant_marking) - float group = decodeFloatRGB(texture2D(tGroupTex, vUv).rgb); - float vMarker = readFromTexture(tMarker, vInstance * float(uGroupCount) + group, uMarkerTexDim).a; + #if defined(dMarkerType_uniform) + float marker = uMarker; + #elif defined(dMarkerType_groupInstance) + float group = decodeFloatRGB(texture2D(tGroupTex, vUv).rgb); + float marker = readFromTexture(tMarker, vInstance * float(uGroupCount) + group, uMarkerTexDim).a; + marker = floor(marker * 255.0 + 0.5); // rounding required to work on some cards on win + #endif #if defined(dRenderVariant_markingDepth) - if (vMarker > 0.0 || imageData.a < 0.05) + if (marker > 0.0 || imageData.a < 0.05) discard; gl_FragColor = packDepthToRGBA(gl_FragCoord.z); #elif defined(dRenderVariant_markingMask) - if (vMarker == 0.0 || imageData.a < 0.05) + if (marker == 0.0 || imageData.a < 0.05) discard; float depthTest = 1.0; if (uMarkingDepthTest) { depthTest = (fragmentDepth >= getDepth(gl_FragCoord.xy / uDrawingBufferSize)) ? 1.0 : 0.0; } - bool isHighlight = intMod(floor(vMarker * 255.0 + 0.5), 2.0) > 0.1; + bool isHighlight = intMod(marker, 2.0) > 0.1; gl_FragColor = vec4(0.0, depthTest, isHighlight ? 1.0 : 0.0, 1.0); #endif #elif defined(dRenderVariant_color) @@ -138,8 +143,13 @@ void main() { gl_FragColor = imageData; gl_FragColor.a *= uAlpha; - float group = decodeFloatRGB(texture2D(tGroupTex, vUv).rgb); - float vMarker = readFromTexture(tMarker, vInstance * float(uGroupCount) + group, uMarkerTexDim).a; + #if defined(dMarkerType_uniform) + float marker = uMarker; + #elif defined(dMarkerType_groupInstance) + float group = decodeFloatRGB(texture2D(tGroupTex, vUv).rgb); + float marker = readFromTexture(tMarker, vInstance * float(uGroupCount) + group, uMarkerTexDim).a; + marker = floor(marker * 255.0 + 0.5); // rounding required to work on some cards on win + #endif #include apply_marker_color #include apply_fog diff --git a/src/mol-repr/structure/complex-visual.ts b/src/mol-repr/structure/complex-visual.ts index 7dc4a1e654dbcee0b37ec0eea32c53c9024a8a00..8f503ace41d9dd8bb1dfafdea68a19a9d14b2041 100644 --- a/src/mol-repr/structure/complex-visual.ts +++ b/src/mol-repr/structure/complex-visual.ts @@ -67,6 +67,7 @@ export function ComplexVisual<G extends Geometry, P extends StructureParams & Ge const { defaultProps, createGeometry, createLocationIterator, getLoci, eachLocation, setUpdateState, mustRecreate, processValues, dispose } = builder; const { updateValues, updateBoundingSphere, updateRenderableState, createPositionIterator } = builder.geometryUtils; const updateState = VisualUpdateState.create(); + const previousMark: Visual.PreviousMark = { loci: EmptyLoci, action: MarkerAction.None, status: -1 }; let renderObject: GraphicsRenderObject<G['kind']> | undefined; @@ -235,7 +236,7 @@ export function ComplexVisual<G extends Geometry, P extends StructureParams & Ge return renderObject ? getLoci(pickingId, currentStructure, renderObject.id) : EmptyLoci; }, mark(loci: Loci, action: MarkerAction) { - return Visual.mark(renderObject, loci, action, lociApply); + return Visual.mark(renderObject, loci, action, lociApply, previousMark); }, setVisibility(visible: boolean) { Visual.setVisibility(renderObject, visible); diff --git a/src/mol-repr/structure/units-visual.ts b/src/mol-repr/structure/units-visual.ts index fd28a68df566f079482e74d7e1741009849fc20c..8acaf871bab614b675e685ea392ad9bcc19d4017 100644 --- a/src/mol-repr/structure/units-visual.ts +++ b/src/mol-repr/structure/units-visual.ts @@ -71,6 +71,7 @@ export function UnitsVisual<G extends Geometry, P extends StructureParams & Geom const { defaultProps, createGeometry, createLocationIterator, getLoci, eachLocation, setUpdateState, mustRecreate, processValues, dispose } = builder; const { createEmpty: createEmptyGeometry, updateValues, updateBoundingSphere, updateRenderableState, createPositionIterator } = builder.geometryUtils; const updateState = VisualUpdateState.create(); + const previousMark: Visual.PreviousMark = { loci: EmptyLoci, action: MarkerAction.None, status: -1 }; let renderObject: GraphicsRenderObject<G['kind']> | undefined; @@ -289,7 +290,7 @@ export function UnitsVisual<G extends Geometry, P extends StructureParams & Geom return renderObject ? getLoci(pickingId, currentStructureGroup, renderObject.id) : EmptyLoci; }, mark(loci: Loci, action: MarkerAction) { - return Visual.mark(renderObject, loci, action, lociApply); + return Visual.mark(renderObject, loci, action, lociApply, previousMark); }, setVisibility(visible: boolean) { Visual.setVisibility(renderObject, visible); diff --git a/src/mol-repr/visual.ts b/src/mol-repr/visual.ts index 334d52fca7d8253f583011e64c074c5f85512986..6c10097e6edfdf52afaa3489a1e26f44bb9b297c 100644 --- a/src/mol-repr/visual.ts +++ b/src/mol-repr/visual.ts @@ -7,8 +7,8 @@ import { RuntimeContext } from '../mol-task'; import { GraphicsRenderObject } from '../mol-gl/render-object'; import { PickingId } from '../mol-geo/geometry/picking'; -import { Loci, isEmptyLoci, isEveryLoci } from '../mol-model/loci'; -import { MarkerAction, applyMarkerAction, getMarkerInfo } from '../mol-util/marker-action'; +import { Loci, isEmptyLoci, isEveryLoci, EveryLoci } from '../mol-model/loci'; +import { MarkerAction, applyMarkerAction, getMarkerInfo, setMarkerValue, getPartialMarkerAverage, MarkerActions, MarkerInfo } from '../mol-util/marker-action'; import { ParamDefinition as PD } from '../mol-util/param-definition'; import { WebGLContext } from '../mol-gl/webgl/context'; import { Theme } from '../mol-theme/theme'; @@ -68,32 +68,63 @@ namespace Visual { if (renderObject) renderObject.state.colorOnly = colorOnly; } - export function mark(renderObject: GraphicsRenderObject | undefined, loci: Loci, action: MarkerAction, lociApply: LociApply) { - if (!renderObject) return false; + export type PreviousMark = { loci: Loci, action: MarkerAction, status: MarkerInfo['status'] } - const { tMarker, markerAverage, markerStatus, uGroupCount, instanceCount } = renderObject.values; + export function mark(renderObject: GraphicsRenderObject | undefined, loci: Loci, action: MarkerAction, lociApply: LociApply, previous?: PreviousMark) { + if (!renderObject || isEmptyLoci(loci)) return false; + + const { tMarker, dMarkerType, uMarker, markerAverage, markerStatus, uGroupCount, instanceCount } = renderObject.values; const count = uGroupCount.ref.value * instanceCount.ref.value; const { array } = tMarker.ref.value; + if (!isEveryLoci(loci)) { + let intervalSize = 0; + lociApply(loci, interval => { + intervalSize += Interval.size(interval); + return true; + }, true); + if (intervalSize === count) loci = EveryLoci; + } + let changed = false; let average = -1; - let status = -1; + let status: MarkerInfo['status'] = -1; if (isEveryLoci(loci)) { - changed = applyMarkerAction(array, Interval.ofLength(count), action); - if (changed) { - const info = getMarkerInfo(action, markerStatus.ref.value); - average = info.average; - status = info.status; + const info = getMarkerInfo(action, markerStatus.ref.value); + if (info.status !== -1) { + changed = markerStatus.ref.value !== info.status; + if (changed) setMarkerValue(array, info.status, count); + } else { + changed = applyMarkerAction(array, Interval.ofLength(count), action); } - } else if (!isEmptyLoci(loci)) { + average = info.average; + status = info.status; + } else { changed = lociApply(loci, interval => applyMarkerAction(array, interval, action), true); + if (changed) { + average = getPartialMarkerAverage(action, markerStatus.ref.value); + if (previous && previous.status !== -1 && average === -1 && + MarkerActions.isReverse(previous.action, action) && + Loci.areEqual(loci, previous.loci) + ) { + status = previous.status; + average = status === 0 ? 0 : 1; + } + } } if (changed) { if (average === -1) { average = getMarkersAverage(array, count); if (average === 0) status = 0; } - ValueCell.update(tMarker, tMarker.ref.value); + if (previous) { + previous.action = action; + previous.loci = loci; + previous.status = markerStatus.ref.value as MarkerInfo['status']; + } + ValueCell.updateIfChanged(uMarker, status); + if (status === -1) ValueCell.update(tMarker, tMarker.ref.value); + ValueCell.updateIfChanged(dMarkerType, status === -1 ? 'groupInstance' : 'uniform'); ValueCell.updateIfChanged(markerAverage, average); ValueCell.updateIfChanged(markerStatus, status); } diff --git a/src/mol-util/marker-action.ts b/src/mol-util/marker-action.ts index 3964968cea4bbbc14cd85ae859a0202007f05040..04e0becaeb2adfce2cbd74c105788fba602eaefb 100644 --- a/src/mol-util/marker-action.ts +++ b/src/mol-util/marker-action.ts @@ -35,6 +35,20 @@ export namespace MarkerActions { MarkerAction.Select | MarkerAction.Deselect | MarkerAction.Toggle | MarkerAction.Clear ) as MarkerActions; + + export function isReverse(a: MarkerAction, b: MarkerAction) { + return ( + (a === MarkerAction.Highlight && b === MarkerAction.RemoveHighlight) || + (a === MarkerAction.RemoveHighlight && b === MarkerAction.Highlight) || + (a === MarkerAction.Select && b === MarkerAction.Deselect) || + (a === MarkerAction.Deselect && b === MarkerAction.Select) || + (a === MarkerAction.Toggle && b === MarkerAction.Toggle) + ); + } +} + +export function setMarkerValue(array: Uint8Array, status: 0 | 1 | 2 | 3, count: number) { + array.fill(status, 0, count); } export function applyMarkerActionAtPosition(array: Uint8Array, i: number, action: MarkerAction) { @@ -204,4 +218,58 @@ export function getMarkerInfo(action: MarkerAction, currentStatus: number): Mark break; } return { average, status }; +} + +/** + * Assumes the action is applied to a partial set that is + * neither the empty set nor the full set. + */ +export function getPartialMarkerAverage(action: MarkerAction, currentStatus: number): MarkerInfo['average'] { + switch (action) { + case MarkerAction.Highlight: + return 1; + case MarkerAction.RemoveHighlight: + if (currentStatus === 0) { + return 0; + } else if (currentStatus === 1) { + return -1; + } else if (currentStatus === 2 || currentStatus === 3) { + return 1; + } + return -1; + case MarkerAction.Select: + return 1; + case MarkerAction.Deselect: + if (currentStatus === 1 || currentStatus === 3) { + return 1; + } else if (currentStatus === 0) { + return 0; + } else if (currentStatus === 2) { + return -1; + } + return -1; + case MarkerAction.Toggle: + if (currentStatus === 1) { + return 1; + } else if (currentStatus === 2) { + return 1; + } else if (currentStatus === 3) { + return 1; + } else if (currentStatus === 0) { + return 1; + } + return -1; + case MarkerAction.Clear: + if (currentStatus === 1) { + return 1; + } else if (currentStatus === 2) { + return 1; + } else if (currentStatus === 3) { + return 1; + } else if (currentStatus === 0) { + return 0; + } + return -1; + } + return -1; } \ No newline at end of file