diff --git a/app/components/Viewer/ContextMenuItem.vue b/app/components/Viewer/ContextMenuItem.vue index 46341c53..fe5826fe 100644 --- a/app/components/Viewer/ContextMenuItem.vue +++ b/app/components/Viewer/ContextMenuItem.vue @@ -96,8 +96,9 @@ function toggleOptions() { variant="panel" padding="pa-0" class="elevation-24" + style="overflow: hidden; display: flex; flex-direction: column" > - + diff --git a/app/components/Viewer/Generic/Model/ModelStyleCard.vue b/app/components/Viewer/Generic/Model/ModelStyleCard.vue index 7a3fe8d6..5e0f737f 100644 --- a/app/components/Viewer/Generic/Model/ModelStyleCard.vue +++ b/app/components/Viewer/Generic/Model/ModelStyleCard.vue @@ -1,11 +1,14 @@ diff --git a/app/components/Viewer/ObjectTree/Views/ModelComponents.vue b/app/components/Viewer/ObjectTree/Views/ModelComponents.vue index 92a664e4..7a011d03 100644 --- a/app/components/Viewer/ObjectTree/Views/ModelComponents.vue +++ b/app/components/Viewer/ObjectTree/Views/ModelComponents.vue @@ -52,6 +52,17 @@ async function onSelectionChange(current) { } hybridViewerStore.remoteRender(); } + +function showContextMenu(event, item) { + const actualItem = item.raw || item; + emit("show-menu", { + event, + itemId: actualItem.category ? actualItem.id : viewId, + context_type: actualItem.category ? "model_component" : "model_component_type", + modelId: viewId, + modelComponentType: actualItem.category ? undefined : actualItem.id, + }); +} diff --git a/app/components/Viewer/Options/OptionsSection.vue b/app/components/Viewer/Options/OptionsSection.vue new file mode 100644 index 00000000..094b7e98 --- /dev/null +++ b/app/components/Viewer/Options/OptionsSection.vue @@ -0,0 +1,74 @@ + + + + + diff --git a/app/stores/data.js b/app/stores/data.js index 4fe00717..724d312f 100644 --- a/app/stores/data.js +++ b/app/stores/data.js @@ -184,10 +184,10 @@ export const useDataStore = defineStore("data", () => { await database.model_components_relation.where("id").equals(modelId).delete(); } - async function getMeshComponentGeodeIds(modelId, component_type) { + async function getMeshComponentGeodeIds(modelId, type) { const components = await database.model_components .where("[id+type]") - .equals([modelId, component_type]) + .equals([modelId, type]) .toArray(); return components.map((component) => component.geode_id); } diff --git a/app/stores/data_style.js b/app/stores/data_style.js index 9b182e7b..da805e20 100644 --- a/app/stores/data_style.js +++ b/app/stores/data_style.js @@ -45,12 +45,14 @@ export const useDataStyleStore = defineStore("dataStyle", () => { return { styles: dataStyleState.styles, componentStyles: dataStyleState.componentStyles, + modelComponentTypeStyles: dataStyleState.modelComponentTypeStyles, }; } async function importStores(snapshot) { const stylesSnapshot = snapshot.styles; const componentStylesSnapshot = snapshot.componentStyles; + const modelComponentTypeStylesSnapshot = snapshot.modelComponentTypeStyles; await dataStyleState.clear(); @@ -60,12 +62,19 @@ export const useDataStyleStore = defineStore("dataStyle", () => { const component_style_promises = Object.values(componentStylesSnapshot).map((style) => database.model_component_datastyle.put(structuredClone(style)), ); + const model_component_type_style_promises = Object.values(modelComponentTypeStylesSnapshot).map( + (style) => database.model_component_type_datastyle.put(structuredClone(style)), + ); - await Promise.all([...style_promises, ...component_style_promises]); + await Promise.all([ + ...style_promises, + ...component_style_promises, + ...model_component_type_style_promises, + ]); } function applyAllStylesFromState() { - const ids = Object.keys(dataStyleState.styles); + const ids = Object.keys(dataStyleState.styles.value); const promises = ids.map(async (id) => { const meta = await dataStore.item(id); const viewerType = meta.viewer_type; diff --git a/app/stores/menu.js b/app/stores/menu.js index 9ae06c7c..e112fc77 100644 --- a/app/stores/menu.js +++ b/app/stores/menu.js @@ -117,6 +117,9 @@ const menusData = { Section: Section_menu, StructuralModel: StructuralModel_menu, }, + model_component_type: { + type: ModelComponent_menu, + }, model_component: { component: ModelComponent_menu, }, diff --git a/app/utils/default_styles.js b/app/utils/default_styles.js index d2690611..1e175457 100644 --- a/app/utils/default_styles.js +++ b/app/utils/default_styles.js @@ -21,6 +21,15 @@ const surfaces_defaultColor = { r: 255, g: 255, b: 255 }; const blocks_defaultVisibility = true; const blocks_defaultColor = { r: 255, g: 255, b: 255 }; +const DEFAULT_MODEL_COMPONENT_TYPE_COLORS = { + Corner: corners_defaultColor, + Line: lines_defaultColor, + Surface: surfaces_defaultColor, + Block: blocks_defaultColor, +}; + +const MESH_TYPES = ["Corner", "Line", "Surface", "Block"]; + // Mesh functions function meshPointsDefaultStyle( visibility = points_defaultVisibility, @@ -315,4 +324,4 @@ function getDefaultStyle(type) { return default_styles()[type]; } -export { getDefaultStyle }; +export { getDefaultStyle, DEFAULT_MODEL_COMPONENT_TYPE_COLORS, MESH_TYPES }; diff --git a/internal/database/base_database.js b/internal/database/base_database.js index 4f5c1793..a61c9f29 100644 --- a/internal/database/base_database.js +++ b/internal/database/base_database.js @@ -2,6 +2,7 @@ import { Dexie } from "dexie"; import { dataStyleTable } from "./tables/data_style"; import { dataTable } from "./tables/data"; import { modelComponentDataStyleTable } from "./tables/model_component_datastyle"; +import { modelComponentTypeDataStyleTable } from "./tables/model_component_type_datastyle"; import { modelComponentsRelationTable } from "./tables/model_components_relation"; import { modelComponentsTable } from "./tables/model_components"; @@ -12,6 +13,7 @@ export class BaseDatabase extends Dexie { [modelComponentsTable.name]: modelComponentsTable.schema, [dataStyleTable.name]: dataStyleTable.schema, [modelComponentDataStyleTable.name]: modelComponentDataStyleTable.schema, + [modelComponentTypeDataStyleTable.name]: modelComponentTypeDataStyleTable.schema, [modelComponentsRelationTable.name]: modelComponentsRelationTable.schema, treeview_config: "id", }; diff --git a/internal/database/database.js b/internal/database/database.js index f59a2227..760ac001 100644 --- a/internal/database/database.js +++ b/internal/database/database.js @@ -59,6 +59,7 @@ class Database extends BaseDatabase { await Dexie.delete("Database"); const databaseContainer = { instance: new Database() }; +databaseContainer.instance.clear(); const database = new Proxy( {}, diff --git a/internal/database/tables/model_component_type_datastyle.js b/internal/database/tables/model_component_type_datastyle.js new file mode 100644 index 00000000..edb2734a --- /dev/null +++ b/internal/database/tables/model_component_type_datastyle.js @@ -0,0 +1,4 @@ +export const modelComponentTypeDataStyleTable = { + name: "model_component_type_datastyle", + schema: "[id_model+type], id_model", +}; diff --git a/internal/stores/data_style/model/blocks/color.js b/internal/stores/data_style/model/blocks/color.js index 6ecbec88..eca644fa 100644 --- a/internal/stores/data_style/model/blocks/color.js +++ b/internal/stores/data_style/model/blocks/color.js @@ -1,46 +1,20 @@ -// Third party imports -import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json"; - -// Local imports -import { useDataStore } from "@ogw_front/stores/data"; import { useModelBlocksCommonStyle } from "./common"; -import { useViewerStore } from "@ogw_front/stores/viewer"; +import { useModelCommonStyle } from "@ogw_internal/stores/data_style/model/common"; +import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json"; -// Local constants -const model_blocks_schemas = viewer_schemas.opengeodeweb_viewer.model.blocks; +const schema = viewer_schemas.opengeodeweb_viewer.model.blocks.color; -export function useModelBlocksColorStyle() { - const dataStore = useDataStore(); - const viewerStore = useViewerStore(); +export function useModelBlocksColor() { + const modelCommonStyle = useModelCommonStyle(); const modelBlocksCommonStyle = useModelBlocksCommonStyle(); function modelBlockColor(id, block_id) { return modelBlocksCommonStyle.modelBlockStyle(id, block_id).color; } - function setModelBlocksColor(id, block_ids, color) { - if (!block_ids || block_ids.length === 0) { - return Promise.resolve(); - } - return dataStore.getMeshComponentsViewerIds(id, block_ids).then((block_viewer_ids) => { - if (!block_viewer_ids || block_viewer_ids.length === 0) { - return modelBlocksCommonStyle.mutateModelBlocksStyle(id, block_ids, { - color, - }); - } - return viewerStore.request( - model_blocks_schemas.color, - { id, block_ids: block_viewer_ids, color }, - { - response_function: () => - modelBlocksCommonStyle.mutateModelBlocksStyle(id, block_ids, { color }), - }, - ); - }); + function setModelBlocksColor(modelId, blocks_ids, color, color_mode = "constant") { + return modelCommonStyle.setModelTypeColor(modelId, blocks_ids, color, schema, color_mode); } - return { - modelBlockColor, - setModelBlocksColor, - }; + return { setModelBlocksColor, modelBlockColor }; } diff --git a/internal/stores/data_style/model/blocks/common.js b/internal/stores/data_style/model/blocks/common.js index a1e8d9a5..c297f837 100644 --- a/internal/stores/data_style/model/blocks/common.js +++ b/internal/stores/data_style/model/blocks/common.js @@ -1,8 +1,10 @@ import merge from "lodash/merge"; import { useDataStyleState } from "@ogw_internal/stores/data_style/state"; +import { useModelCommonStyle } from "@ogw_internal/stores/data_style/model/common"; export function useModelBlocksCommonStyle() { const dataStyleState = useDataStyleState(); + const modelCommonStyle = useModelCommonStyle(); function modelBlocksStyle(id) { return dataStyleState.getStyle(id).blocks; @@ -14,12 +16,12 @@ export function useModelBlocksCommonStyle() { return merge({}, groupStyle, individualStyle); } - function mutateModelBlocksStyle(id, block_ids, values) { - return dataStyleState.mutateComponentStyles(id, block_ids, values); + function mutateModelBlocksStyle(id, blocks_ids, values) { + return modelCommonStyle.mutateComponentStyles(id, blocks_ids, values); } function mutateModelBlockStyle(id, block_id, values) { - return dataStyleState.mutateComponentStyle(id, block_id, values); + return modelCommonStyle.mutateComponentStyle(id, block_id, values); } return { diff --git a/internal/stores/data_style/model/blocks/index.js b/internal/stores/data_style/model/blocks/index.js index fad9dd8a..ce6b4f5b 100644 --- a/internal/stores/data_style/model/blocks/index.js +++ b/internal/stores/data_style/model/blocks/index.js @@ -1,54 +1,52 @@ -// Local imports import { useDataStore } from "@ogw_front/stores/data"; -import { useModelBlocksColorStyle } from "./color"; +import { useModelBlocksColor } from "./color"; import { useModelBlocksCommonStyle } from "./common"; -import { useModelBlocksVisibilityStyle } from "./visibility"; +import { useModelBlocksVisibility } from "./visibility"; + async function setModelBlocksDefaultStyle(_id) { // Placeholder } export function useModelBlocksStyle() { const dataStore = useDataStore(); - const modelBlocksCommonStyle = useModelBlocksCommonStyle(); - const modelBlocksVisibilityStyle = useModelBlocksVisibilityStyle(); - const modelBlocksColorStyle = useModelBlocksColorStyle(); + const commonStyle = useModelBlocksCommonStyle(); + const visibilityStyle = useModelBlocksVisibility(); + const colorStyle = useModelBlocksColor(); - async function applyModelBlocksStyle(id) { - const block_ids = await dataStore.getBlocksGeodeIds(id); - if (block_ids.length === 0) { + async function applyModelBlocksStyle(modelId) { + const blocks_ids = await dataStore.getBlocksGeodeIds(modelId); + if (!blocks_ids?.length) { return; } const visibilityGroups = {}; const colorGroups = {}; - for (const block_id of block_ids) { - const style = modelBlocksCommonStyle.modelBlockStyle(id, block_id); + for (const block_id of blocks_ids) { + const style = commonStyle.modelBlockStyle(modelId, block_id); - const vKey = String(style.visibility); - if (!visibilityGroups[vKey]) { - visibilityGroups[vKey] = []; + const visibility = String(style.visibility); + if (!visibilityGroups[visibility]) { + visibilityGroups[visibility] = []; } - visibilityGroups[vKey].push(block_id); + visibilityGroups[visibility].push(block_id); - const cKey = JSON.stringify(style.color); - if (!colorGroups[cKey]) { - colorGroups[cKey] = []; + const color_mode = style.color_mode || "constant"; + const color_key = color_mode === "random" ? "random" : JSON.stringify(style.color); + if (!colorGroups[color_key]) { + colorGroups[color_key] = { color_mode, color: style.color, blocks_ids: [] }; } - colorGroups[cKey].push(block_id); + colorGroups[color_key].blocks_ids.push(block_id); } - const promises = []; - - for (const [vValue, ids] of Object.entries(visibilityGroups)) { - promises.push( - modelBlocksVisibilityStyle.setModelBlocksVisibility(id, ids, vValue === "true"), - ); - } - - for (const [cValue, ids] of Object.entries(colorGroups)) { - promises.push(modelBlocksColorStyle.setModelBlocksColor(id, ids, JSON.parse(cValue))); - } + const promises = [ + ...Object.entries(visibilityGroups).map(([visibility, ids]) => + visibilityStyle.setModelBlocksVisibility(modelId, ids, visibility === "true"), + ), + ...Object.values(colorGroups).map(({ color_mode, color, blocks_ids: ids }) => + colorStyle.setModelBlocksColor(modelId, ids, color, color_mode), + ), + ]; return Promise.all(promises); } @@ -56,8 +54,8 @@ export function useModelBlocksStyle() { return { applyModelBlocksStyle, setModelBlocksDefaultStyle, - ...modelBlocksCommonStyle, - ...modelBlocksVisibilityStyle, - ...modelBlocksColorStyle, + ...commonStyle, + ...visibilityStyle, + ...colorStyle, }; } diff --git a/internal/stores/data_style/model/blocks/visibility.js b/internal/stores/data_style/model/blocks/visibility.js index 382e320c..43cf3c8d 100644 --- a/internal/stores/data_style/model/blocks/visibility.js +++ b/internal/stores/data_style/model/blocks/visibility.js @@ -1,47 +1,20 @@ -// Third party imports -import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json"; - -// Local imports -import { useDataStore } from "@ogw_front/stores/data"; import { useModelBlocksCommonStyle } from "./common"; -import { useViewerStore } from "@ogw_front/stores/viewer"; +import { useModelCommonStyle } from "@ogw_internal/stores/data_style/model/common"; +import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json"; -// Local constants -const model_blocks_schemas = viewer_schemas.opengeodeweb_viewer.model.blocks; +const schema = viewer_schemas.opengeodeweb_viewer.model.blocks.visibility; -export function useModelBlocksVisibilityStyle() { - const dataStore = useDataStore(); - const viewerStore = useViewerStore(); +export function useModelBlocksVisibility() { + const modelCommonStyle = useModelCommonStyle(); const modelBlocksCommonStyle = useModelBlocksCommonStyle(); function modelBlockVisibility(id, block_id) { - const style = modelBlocksCommonStyle.modelBlockStyle(id, block_id); - return style.visibility ?? true; + return modelBlocksCommonStyle.modelBlockStyle(id, block_id).visibility; } - function setModelBlocksVisibility(id, block_ids, visibility) { - if (!block_ids || block_ids.length === 0) { - return Promise.resolve(); - } - return dataStore.getMeshComponentsViewerIds(id, block_ids).then((block_viewer_ids) => { - if (!block_viewer_ids || block_viewer_ids.length === 0) { - return modelBlocksCommonStyle.mutateModelBlocksStyle(id, block_ids, { - visibility, - }); - } - return viewerStore.request( - model_blocks_schemas.visibility, - { id, block_ids: block_viewer_ids, visibility }, - { - response_function: () => - modelBlocksCommonStyle.mutateModelBlocksStyle(id, block_ids, { visibility }), - }, - ); - }); + function setModelBlocksVisibility(modelId, blocks_ids, visibility) { + return modelCommonStyle.setModelTypeVisibility(modelId, blocks_ids, visibility, schema); } - return { - modelBlockVisibility, - setModelBlocksVisibility, - }; + return { setModelBlocksVisibility, modelBlockVisibility }; } diff --git a/internal/stores/data_style/model/color.js b/internal/stores/data_style/model/color.js new file mode 100644 index 00000000..5b4d3287 --- /dev/null +++ b/internal/stores/data_style/model/color.js @@ -0,0 +1,119 @@ +import { DEFAULT_MODEL_COMPONENT_TYPE_COLORS } from "@ogw_front/utils/default_styles"; +import { dispatchToComponentTypes } from "./visibility"; +import { useDataStore } from "@ogw_front/stores/data"; +import { useDataStyleState } from "@ogw_internal/stores/data_style/state"; +import { useModelCommonStyle } from "@ogw_internal/stores/data_style/model/common"; +import { useViewerStore } from "@ogw_front/stores/viewer"; + +function useModelColorStyle(componentStyleFunctions) { + const dataStore = useDataStore(); + const dataStyleState = useDataStyleState(); + const viewerStore = useViewerStore(); + const modelCommonStyle = useModelCommonStyle(); + + function getModelComponentColor(modelId, componentId) { + return dataStyleState.getComponentStyle(modelId, componentId).color; + } + + function getModelComponentEffectiveColor(modelId, componentId, type) { + const individualColor = getModelComponentColor(modelId, componentId); + if (individualColor !== undefined) { + return individualColor; + } + return getModelComponentTypeColor(modelId, type); + } + + function getModelComponentColorMode(modelId, componentId) { + return dataStyleState.getComponentStyle(modelId, componentId).color_mode || "constant"; + } + + function getModelComponentTypeColor(modelId, type) { + return ( + dataStyleState.getModelComponentTypeStyle(modelId, type).color || + DEFAULT_MODEL_COMPONENT_TYPE_COLORS[type] + ); + } + + function getModelComponentTypeColorMode(modelId, type) { + return dataStyleState.getModelComponentTypeStyle(modelId, type).color_mode || "constant"; + } + + async function setModelComponentTypeColor(modelId, type, color) { + viewerStore.start_request(); + try { + await modelCommonStyle.mutateModelComponentTypeStyle(modelId, type, { + color, + color_mode: "constant", + }); + const idsForType = await dataStore.getMeshComponentGeodeIds(modelId, type); + if (idsForType.length === 0) { + return; + } + await setModelComponentsColor(modelId, idsForType, color); + } finally { + viewerStore.stop_request(); + } + } + + async function setModelComponentTypeColorMode(modelId, type, color_mode) { + viewerStore.start_request(); + try { + await modelCommonStyle.mutateModelComponentTypeStyle(modelId, type, { color_mode }); + const idsForType = await dataStore.getMeshComponentGeodeIds(modelId, type); + if (idsForType.length === 0) { + return; + } + + if (color_mode === "random") { + await setModelComponentsColor(modelId, idsForType, undefined, color_mode); + return; + } + await modelCommonStyle.mutateComponentStyles(modelId, idsForType, { color_mode }); + } finally { + viewerStore.stop_request(); + } + } + + async function setModelComponentColorMode(modelId, componentId, color_mode) { + viewerStore.start_request(); + try { + await modelCommonStyle.mutateComponentStyle(modelId, componentId, { color_mode }); + if (color_mode === "random") { + await setModelComponentsColor(modelId, [componentId], undefined, color_mode); + } + } finally { + viewerStore.stop_request(); + } + } + + async function setModelComponentsColor(modelId, componentIds, color, color_mode = "constant") { + viewerStore.start_request(); + try { + await modelCommonStyle.mutateComponentStyles(modelId, componentIds, { color, color_mode }); + return await dispatchToComponentTypes( + modelId, + componentIds, + "Color", + { componentStyleFunctions }, + color, + color_mode, + ); + } finally { + viewerStore.stop_request(); + } + } + + return { + getModelComponentColor, + getModelComponentEffectiveColor, + getModelComponentColorMode, + getModelComponentTypeColor, + getModelComponentTypeColorMode, + setModelComponentTypeColor, + setModelComponentTypeColorMode, + setModelComponentColorMode, + setModelComponentsColor, + }; +} + +export { useModelColorStyle }; diff --git a/internal/stores/data_style/model/common.js b/internal/stores/data_style/model/common.js new file mode 100644 index 00000000..37998766 --- /dev/null +++ b/internal/stores/data_style/model/common.js @@ -0,0 +1,132 @@ +import { database } from "@ogw_internal/database/database"; +import merge from "lodash/merge"; +import { useDataStore } from "@ogw_front/stores/data"; +import { useViewerStore } from "@ogw_front/stores/viewer"; + +export function useModelCommonStyle() { + const dataStore = useDataStore(); + const viewerStore = useViewerStore(); + + async function mutateComponentStyle(id_model, id_component, values) { + const table = database.model_component_datastyle; + const key = [id_model, id_component]; + const entry = (await table.get(key)) || { id_model, id_component }; + merge(entry, values); + return table.put(structuredClone(toRaw(entry))); + } + + function mutateModelComponentTypeStyle(id_model, type, values) { + return database.transaction("rw", database.model_component_type_datastyle, async () => { + const table = database.model_component_type_datastyle; + const key = [id_model, type]; + const entry = (await table.get(key)) || { id_model, type }; + merge(entry, values); + return table.put(structuredClone(toRaw(entry))); + }); + } + + function mutateComponentStyles(id_model, id_components, values) { + return database.transaction("rw", database.model_component_datastyle, async () => { + const all_styles = await database.model_component_datastyle + .where("id_model") + .equals(id_model) + .toArray(); + + const style_map = {}; + for (const style of all_styles) { + style_map[style.id_component] = style; + } + + const updates = id_components.map((id_component) => { + const style = style_map[id_component] || { id_model, id_component }; + merge(style, values); + return toRaw(style); + }); + + return database.model_component_datastyle.bulkPut(structuredClone(updates)); + }); + } + + function bulkMutateComponentStylesPerComponent(id_model, component_updates) { + return database.transaction("rw", database.model_component_datastyle, async () => { + const component_ids = new Set(component_updates.map((update) => update.id_component)); + const all_styles = await database.model_component_datastyle + .where("id_model") + .equals(id_model) + .and((style) => component_ids.has(style.id_component)) + .toArray(); + const style_map = Object.fromEntries(all_styles.map((style) => [style.id_component, style])); + const updates = component_updates.map(({ id_component, values }) => { + const style = style_map[id_component] || { id_model, id_component }; + merge(style, values); + return toRaw(style); + }); + return database.model_component_datastyle.bulkPut(structuredClone(updates)); + }); + } + + async function setModelTypeColor(id, component_ids, color, schema, color_mode = "constant") { + if (!component_ids?.length) { + return; + } + + const viewer_ids = await dataStore.getMeshComponentsViewerIds(id, component_ids); + if (!viewer_ids?.length) { + return; + } + + const params = { id, block_ids: viewer_ids, color_mode }; + if (color_mode === "constant" && color !== undefined) { + params.color = color; + } + + return viewerStore.request(schema, params, { + response_function: async (colors) => { + if (color_mode === "constant" && color !== undefined) { + await mutateComponentStyles(id, component_ids, { color }); + return; + } + + if (!colors?.length) { + return; + } + + await bulkMutateComponentStylesPerComponent( + id, + colors.map(({ geode_id, color: color_value }) => ({ + id_component: geode_id, + values: { color: color_value }, + })), + ); + }, + }); + } + + async function setModelTypeVisibility(id, component_ids, visibility, schema) { + if (!component_ids?.length) { + return; + } + + const viewer_ids = await dataStore.getMeshComponentsViewerIds(id, component_ids); + if (!viewer_ids?.length) { + return; + } + + return viewerStore.request( + schema, + { id, block_ids: viewer_ids, visibility }, + { + response_function: () => mutateComponentStyles(id, component_ids, { visibility }), + }, + ); + } + + return { + mutateComponentStyle, + mutateModelComponentTypeStyle, + mutateComponentStyles, + bulkMutateComponentStylesPerComponent, + setModelTypeColor, + setModelTypeVisibility, + }; +} diff --git a/internal/stores/data_style/model/corners/color.js b/internal/stores/data_style/model/corners/color.js index 750d3a8f..f78d5453 100644 --- a/internal/stores/data_style/model/corners/color.js +++ b/internal/stores/data_style/model/corners/color.js @@ -1,44 +1,20 @@ -// Third party imports -import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json"; - -// Local imports -import { useDataStore } from "@ogw_front/stores/data"; +import { useModelCommonStyle } from "@ogw_internal/stores/data_style/model/common"; import { useModelCornersCommonStyle } from "./common"; -import { useViewerStore } from "@ogw_front/stores/viewer"; +import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json"; -// Local constants -const model_corners_schemas = viewer_schemas.opengeodeweb_viewer.model.corners; +const schema = viewer_schemas.opengeodeweb_viewer.model.corners.color; -export function useModelCornersColorStyle() { - const dataStore = useDataStore(); - const viewerStore = useViewerStore(); +export function useModelCornersColor() { + const modelCommonStyle = useModelCommonStyle(); const modelCornersCommonStyle = useModelCornersCommonStyle(); function modelCornerColor(id, corner_id) { return modelCornersCommonStyle.modelCornerStyle(id, corner_id).color; } - function setModelCornersColor(id, corner_ids, color) { - if (!corner_ids || corner_ids.length === 0) { - return Promise.resolve(); - } - return dataStore.getMeshComponentsViewerIds(id, corner_ids).then((corner_viewer_ids) => { - if (!corner_viewer_ids || corner_viewer_ids.length === 0) { - return modelCornersCommonStyle.mutateModelCornersStyle(id, corner_ids, { color }); - } - return viewerStore.request( - model_corners_schemas.color, - { id, block_ids: corner_viewer_ids, color }, - { - response_function: () => - modelCornersCommonStyle.mutateModelCornersStyle(id, corner_ids, { color }), - }, - ); - }); + function setModelCornersColor(modelId, corners_ids, color, color_mode = "constant") { + return modelCommonStyle.setModelTypeColor(modelId, corners_ids, color, schema, color_mode); } - return { - modelCornerColor, - setModelCornersColor, - }; + return { setModelCornersColor, modelCornerColor }; } diff --git a/internal/stores/data_style/model/corners/common.js b/internal/stores/data_style/model/corners/common.js index 7357fc5f..c426c084 100644 --- a/internal/stores/data_style/model/corners/common.js +++ b/internal/stores/data_style/model/corners/common.js @@ -1,8 +1,10 @@ import merge from "lodash/merge"; import { useDataStyleState } from "@ogw_internal/stores/data_style/state"; +import { useModelCommonStyle } from "@ogw_internal/stores/data_style/model/common"; export function useModelCornersCommonStyle() { const dataStyleState = useDataStyleState(); + const modelCommonStyle = useModelCommonStyle(); function modelCornersStyle(id) { return dataStyleState.getStyle(id).corners; @@ -14,12 +16,12 @@ export function useModelCornersCommonStyle() { return merge({}, groupStyle, individualStyle); } - function mutateModelCornersStyle(id, corner_ids, values) { - return dataStyleState.mutateComponentStyles(id, corner_ids, values); + function mutateModelCornersStyle(id, corners_ids, values) { + return modelCommonStyle.mutateComponentStyles(id, corners_ids, values); } function mutateModelCornerStyle(id, corner_id, values) { - return dataStyleState.mutateComponentStyle(id, corner_id, values); + return modelCommonStyle.mutateComponentStyle(id, corner_id, values); } return { diff --git a/internal/stores/data_style/model/corners/index.js b/internal/stores/data_style/model/corners/index.js index 63405075..c81e9a5c 100644 --- a/internal/stores/data_style/model/corners/index.js +++ b/internal/stores/data_style/model/corners/index.js @@ -1,59 +1,52 @@ -// Local imports import { useDataStore } from "@ogw_front/stores/data"; -import { useModelCornersColorStyle } from "./color"; +import { useModelCornersColor } from "./color"; import { useModelCornersCommonStyle } from "./common"; -import { useModelCornersVisibilityStyle } from "./visibility"; +import { useModelCornersVisibility } from "./visibility"; + async function setModelCornersDefaultStyle(_id) { // Placeholder } export function useModelCornersStyle() { const dataStore = useDataStore(); - const modelCornersCommonStyle = useModelCornersCommonStyle(); - const modelCornersVisibilityStyle = useModelCornersVisibilityStyle(); - const modelCornersColorStyle = useModelCornersColorStyle(); + const commonStyle = useModelCornersCommonStyle(); + const visibilityStyle = useModelCornersVisibility(); + const colorStyle = useModelCornersColor(); - async function applyModelCornersStyle(id) { - const corner_ids = await dataStore.getCornersGeodeIds(id); - if (corner_ids.length === 0) { + async function applyModelCornersStyle(modelId) { + const corners_ids = await dataStore.getCornersGeodeIds(modelId); + if (!corners_ids?.length) { return; } - // Group corners by their effective style to minimize RPC calls const visibilityGroups = {}; const colorGroups = {}; - for (const corner_id of corner_ids) { - const style = modelCornersCommonStyle.modelCornerStyle(id, corner_id); + for (const corner_id of corners_ids) { + const style = commonStyle.modelCornerStyle(modelId, corner_id); - // Group by visibility - const vKey = String(style.visibility); - if (!visibilityGroups[vKey]) { - visibilityGroups[vKey] = []; + const visibility = String(style.visibility); + if (!visibilityGroups[visibility]) { + visibilityGroups[visibility] = []; } - visibilityGroups[vKey].push(corner_id); + visibilityGroups[visibility].push(corner_id); - // Group by color - const cKey = JSON.stringify(style.color); - if (!colorGroups[cKey]) { - colorGroups[cKey] = []; + const color_mode = style.color_mode || "constant"; + const color_key = color_mode === "random" ? "random" : JSON.stringify(style.color); + if (!colorGroups[color_key]) { + colorGroups[color_key] = { color_mode, color: style.color, corners_ids: [] }; } - colorGroups[cKey].push(corner_id); + colorGroups[color_key].corners_ids.push(corner_id); } - const promises = []; - - // Apply visibility groups - for (const [vValue, ids] of Object.entries(visibilityGroups)) { - promises.push( - modelCornersVisibilityStyle.setModelCornersVisibility(id, ids, vValue === "true"), - ); - } - - // Apply color groups - for (const [cValue, ids] of Object.entries(colorGroups)) { - promises.push(modelCornersColorStyle.setModelCornersColor(id, ids, JSON.parse(cValue))); - } + const promises = [ + ...Object.entries(visibilityGroups).map(([visibility, ids]) => + visibilityStyle.setModelCornersVisibility(modelId, ids, visibility === "true"), + ), + ...Object.values(colorGroups).map(({ color_mode, color, corners_ids: ids }) => + colorStyle.setModelCornersColor(modelId, ids, color, color_mode), + ), + ]; return Promise.all(promises); } @@ -61,8 +54,8 @@ export function useModelCornersStyle() { return { applyModelCornersStyle, setModelCornersDefaultStyle, - ...modelCornersCommonStyle, - ...modelCornersVisibilityStyle, - ...modelCornersColorStyle, + ...commonStyle, + ...visibilityStyle, + ...colorStyle, }; } diff --git a/internal/stores/data_style/model/corners/visibility.js b/internal/stores/data_style/model/corners/visibility.js index 5e764c13..44677be0 100644 --- a/internal/stores/data_style/model/corners/visibility.js +++ b/internal/stores/data_style/model/corners/visibility.js @@ -1,44 +1,20 @@ -// Third party imports -import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json"; - -// Local imports -import { useDataStore } from "@ogw_front/stores/data"; +import { useModelCommonStyle } from "@ogw_internal/stores/data_style/model/common"; import { useModelCornersCommonStyle } from "./common"; -import { useViewerStore } from "@ogw_front/stores/viewer"; +import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json"; -// Local constants -const model_corners_schemas = viewer_schemas.opengeodeweb_viewer.model.corners; +const schema = viewer_schemas.opengeodeweb_viewer.model.corners.visibility; -export function useModelCornersVisibilityStyle() { - const dataStore = useDataStore(); - const viewerStore = useViewerStore(); +export function useModelCornersVisibility() { + const modelCommonStyle = useModelCommonStyle(); const modelCornersCommonStyle = useModelCornersCommonStyle(); function modelCornerVisibility(id, corner_id) { return modelCornersCommonStyle.modelCornerStyle(id, corner_id).visibility; } - function setModelCornersVisibility(id, corner_ids, visibility) { - if (!corner_ids || corner_ids.length === 0) { - return Promise.resolve(); - } - return dataStore.getMeshComponentsViewerIds(id, corner_ids).then((corner_viewer_ids) => { - if (!corner_viewer_ids || corner_viewer_ids.length === 0) { - return modelCornersCommonStyle.mutateModelCornersStyle(id, corner_ids, { visibility }); - } - return viewerStore.request( - model_corners_schemas.visibility, - { id, block_ids: corner_viewer_ids, visibility }, - { - response_function: () => - modelCornersCommonStyle.mutateModelCornersStyle(id, corner_ids, { visibility }), - }, - ); - }); + function setModelCornersVisibility(modelId, corners_ids, visibility) { + return modelCommonStyle.setModelTypeVisibility(modelId, corners_ids, visibility, schema); } - return { - modelCornerVisibility, - setModelCornersVisibility, - }; + return { setModelCornersVisibility, modelCornerVisibility }; } diff --git a/internal/stores/data_style/model/index.js b/internal/stores/data_style/model/index.js index c3c9c454..065a10cf 100644 --- a/internal/stores/data_style/model/index.js +++ b/internal/stores/data_style/model/index.js @@ -1,231 +1,86 @@ -import { database } from "@ogw_internal/database/database"; -import { liveQuery } from "dexie"; import { useDataStore } from "@ogw_front/stores/data"; import { useDataStyleState } from "@ogw_internal/stores/data_style/state"; -import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer"; import { useModelBlocksStyle } from "./blocks"; +import { useModelColorStyle } from "./color"; import { useModelCornersStyle } from "./corners"; import { useModelEdgesStyle } from "./edges"; import { useModelLinesStyle } from "./lines"; import { useModelPointsStyle } from "./points"; +import { useModelSelection } from "./selection"; import { useModelSurfacesStyle } from "./surfaces"; +import { useModelVisibilityStyle } from "./visibility"; import { useViewerStore } from "@ogw_front/stores/viewer"; -import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json"; -const model_schemas = viewer_schemas.opengeodeweb_viewer.model; - -const MESH_CONFIG = [{ type: "Corner" }, { type: "Line" }, { type: "Surface" }, { type: "Block" }]; - -const MESH_TYPES = MESH_CONFIG.map((config) => config.type); - -export function useModelStyle() { +function useModelStyle() { const dataStore = useDataStore(); const dataStyleState = useDataStyleState(); - const modelCornersStyleStore = useModelCornersStyle(); - const modelBlocksStyleStore = useModelBlocksStyle(); - const modelEdgesStyleStore = useModelEdgesStyle(); - const modelLinesStyleStore = useModelLinesStyle(); - const modelPointsStyleStore = useModelPointsStyle(); - const modelSurfacesStyleStore = useModelSurfacesStyle(); - const hybridViewerStore = useHybridViewerStore(); + const modelCornersStyle = useModelCornersStyle(); + const modelBlocksStyle = useModelBlocksStyle(); + const modelEdgesStyle = useModelEdgesStyle(); + const modelLinesStyle = useModelLinesStyle(); + const modelPointsStyle = useModelPointsStyle(); + const modelSurfacesStyle = useModelSurfacesStyle(); const viewerStore = useViewerStore(); - function buildSelection(modelId, components, stylesMap) { - const componentsByType = Object.fromEntries(MESH_TYPES.map((type) => [type, []])); - for (const component of components) { - if (componentsByType[component.type]) { - componentsByType[component.type].push(component); - } - } - - const groupStyles = dataStyleState.getStyle(modelId); - const selection = []; - for (const type of MESH_TYPES) { - const typeComponents = componentsByType[type]; - if (typeComponents.length === 0) { - continue; - } - - const typeKey = `${type.toLowerCase()}s`; - const defaultVisibility = groupStyles[typeKey].visibility; - - let allVisible = true; - for (const component of typeComponents) { - const isVisible = stylesMap[component.geode_id]?.visibility ?? defaultVisibility; - if (isVisible) { - selection.push(component.geode_id); - } else { - allVisible = false; - } - } - if (allVisible) { - selection.push(type); - } - } - return selection; - } - - function modelVisibility(modelId) { - return dataStyleState.getStyle(modelId).visibility; - } + const componentStyleFunctions = { + Corner: modelCornersStyle, + Line: modelLinesStyle, + Surface: modelSurfacesStyle, + Block: modelBlocksStyle, + }; - function setModelVisibility(modelId, visibility) { - return viewerStore.request( - model_schemas.visibility, - { id: modelId, visibility }, - { - response_function: async () => { - await hybridViewerStore.setVisibility(modelId, visibility); - await dataStyleState.mutateStyle(modelId, { visibility }); - return { id: modelId, visibility }; - }, - }, - ); - } + const modelColorStyle = useModelColorStyle(componentStyleFunctions); + const modelVisibilityStyle = useModelVisibilityStyle(componentStyleFunctions); function visibleMeshComponents(id_ref) { - const selection = ref([]); - watch( - () => unref(id_ref), - (modelId, _prev, onCleanup) => { - if (!modelId) { - selection.value = []; - return; - } - const observable = liveQuery(async () => { - const allComponents = await database.model_components - .where("id") - .equals(modelId) - .toArray(); - if (allComponents.length === 0) { - return []; - } - const componentStyles = await database.model_component_datastyle - .where("id_model") - .equals(modelId) - .toArray(); - const stylesMap = Object.fromEntries( - componentStyles.map((style) => [style.id_component, style]), - ); - return buildSelection(modelId, allComponents, stylesMap); - }); - - const subscription = observable.subscribe({ - next: (val) => { - selection.value = val; - }, - }); - onCleanup(() => subscription.unsubscribe()); - }, - { immediate: true }, - ); - return selection; - } - - function getModelComponentColor(modelId, componentId) { - return dataStyleState.getComponentStyle(modelId, componentId).color; - } - - async function setModelComponentsVisibility(modelId, componentIds, visibility) { - const allComponents = await database.model_components.where("id").equals(modelId).toArray(); - const componentsMap = Object.fromEntries( - allComponents.map((component) => [component.geode_id, component]), - ); - - return Promise.all( - MESH_TYPES.map(async (type) => { - const typeComponents = allComponents.filter((component) => component.type === type); - const isSelectedType = componentIds.includes(type); - const idsToUpdate = isSelectedType - ? typeComponents.map((component) => component.geode_id) - : componentIds.filter((id) => componentsMap[id]?.type === type); - - if (idsToUpdate.length === 0) { - return; - } - - const viewerIds = await dataStore.getMeshComponentsViewerIds(modelId, idsToUpdate); - if (viewerIds.length > 0) { - const schema = model_schemas[`${type.toLowerCase()}s`].visibility; - await viewerStore.request(schema, { id: modelId, block_ids: viewerIds, visibility }); - } - return dataStyleState.mutateComponentStyles(modelId, idsToUpdate, { visibility }); - }), - ); - } - - async function setModelComponentsColor(modelId, componentIds, color) { - const allComponents = await database.model_components.where("id").equals(modelId).toArray(); - const componentsMap = Object.fromEntries( - allComponents.map((component) => [component.geode_id, component]), - ); - const handlers = { - Corner: (ids) => modelCornersStyleStore.setModelCornersColor(modelId, ids, color), - Line: (ids) => modelLinesStyleStore.setModelLinesColor(modelId, ids, color), - Surface: (ids) => modelSurfacesStyleStore.setModelSurfacesColor(modelId, ids, color), - Block: (ids) => modelBlocksStyleStore.setModelBlocksColor(modelId, ids, color), - }; - return Promise.all( - MESH_TYPES.map((type) => { - const idsForType = componentIds.filter((id) => componentsMap[id]?.type === type); - return handlers[type](idsForType); - }), - ); + return useModelSelection(id_ref, dataStyleState); } function applyModelStyle(modelId) { const style = dataStyleState.getStyle(modelId); - const handlers = { - visibility: () => setModelVisibility(modelId, style.visibility), - corners: () => modelCornersStyleStore.applyModelCornersStyle(modelId), - lines: () => modelLinesStyleStore.applyModelLinesStyle(modelId), - surfaces: () => modelSurfacesStyleStore.applyModelSurfacesStyle(modelId), - blocks: () => modelBlocksStyleStore.applyModelBlocksStyle(modelId), - points: () => modelPointsStyleStore.applyModelPointsStyle(modelId), - edges: () => modelEdgesStyleStore.applyModelEdgesStyle(modelId), - }; - return Promise.all( - Object.keys(style) - .filter((key) => handlers[key]) - .map((key) => handlers[key]()), - ); + return Promise.all([ + modelVisibilityStyle.setModelVisibility(modelId, style.visibility), + modelBlocksStyle.applyModelBlocksStyle(modelId), + modelSurfacesStyle.applyModelSurfacesStyle(modelId), + modelLinesStyle.applyModelLinesStyle(modelId), + modelCornersStyle.applyModelCornersStyle(modelId), + modelPointsStyle.applyModelPointsStyle(modelId), + modelEdgesStyle.applyModelEdgesStyle(modelId), + ]); } - function setModelMeshComponentsDefaultStyle(modelId) { - return dataStore.item(modelId).then((item) => { + async function setModelMeshComponentsDefaultStyle(modelId) { + viewerStore.start_request(); + try { + const item = await dataStore.item(modelId); if (!item) { - return []; + return; } - const { mesh_components } = item; - const handlers = { - Corner: () => modelCornersStyleStore.setModelCornersDefaultStyle(modelId), - Line: () => modelLinesStyleStore.setModelLinesDefaultStyle(modelId), - Surface: () => modelSurfacesStyleStore.setModelSurfacesDefaultStyle(modelId), - Block: () => modelBlocksStyleStore.setModelBlocksDefaultStyle(modelId), - }; - return Promise.all( - Object.keys(mesh_components) - .filter((key) => handlers[key]) - .map((key) => handlers[key]()), - ); - }); + return await Promise.all([ + modelBlocksStyle.setModelBlocksDefaultStyle(modelId), + modelSurfacesStyle.setModelSurfacesDefaultStyle(modelId), + modelLinesStyle.setModelLinesDefaultStyle(modelId), + modelCornersStyle.setModelCornersDefaultStyle(modelId), + ]); + } finally { + viewerStore.stop_request(); + } } return { - modelVisibility, visibleMeshComponents, - setModelVisibility, - setModelComponentsVisibility, - getModelComponentColor, - setModelComponentsColor, applyModelStyle, setModelMeshComponentsDefaultStyle, - ...modelBlocksStyleStore, - ...modelCornersStyleStore, - ...modelEdgesStyleStore, - ...modelLinesStyleStore, - ...modelPointsStyleStore, - ...modelSurfacesStyleStore, + ...modelColorStyle, + ...modelVisibilityStyle, + ...modelBlocksStyle, + ...modelCornersStyle, + ...modelEdgesStyle, + ...modelLinesStyle, + ...modelPointsStyle, + ...modelSurfacesStyle, }; } + +export { useModelStyle }; diff --git a/internal/stores/data_style/model/lines/color.js b/internal/stores/data_style/model/lines/color.js index 88cd9c4b..70d95421 100644 --- a/internal/stores/data_style/model/lines/color.js +++ b/internal/stores/data_style/model/lines/color.js @@ -1,48 +1,20 @@ -// Third party imports -import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json"; - -// Local imports -import { useDataStore } from "@ogw_front/stores/data"; +import { useModelCommonStyle } from "@ogw_internal/stores/data_style/model/common"; import { useModelLinesCommonStyle } from "./common"; -import { useViewerStore } from "@ogw_front/stores/viewer"; +import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json"; -// Local constants -const model_lines_schemas = viewer_schemas.opengeodeweb_viewer.model.lines; +const schema = viewer_schemas.opengeodeweb_viewer.model.lines.color; -export function useModelLinesColorStyle() { - const dataStore = useDataStore(); - const viewerStore = useViewerStore(); +export function useModelLinesColor() { + const modelCommonStyle = useModelCommonStyle(); const modelLinesCommonStyle = useModelLinesCommonStyle(); function modelLineColor(id, line_id) { return modelLinesCommonStyle.modelLineStyle(id, line_id).color; } - function setModelLinesColor(id, line_ids, color) { - if (!line_ids || line_ids.length === 0) { - return Promise.resolve(); - } - return dataStore.getMeshComponentsViewerIds(id, line_ids).then((line_viewer_ids) => { - if (!line_viewer_ids || line_viewer_ids.length === 0) { - return modelLinesCommonStyle.mutateModelLinesStyle(id, line_ids, { - color, - }); - } - return viewerStore.request( - model_lines_schemas.color, - { id, block_ids: line_viewer_ids, color }, - { - response_function: () => - modelLinesCommonStyle.mutateModelLinesStyle(id, line_ids, { - color, - }), - }, - ); - }); + function setModelLinesColor(modelId, lines_ids, color, color_mode = "constant") { + return modelCommonStyle.setModelTypeColor(modelId, lines_ids, color, schema, color_mode); } - return { - modelLineColor, - setModelLinesColor, - }; + return { setModelLinesColor, modelLineColor }; } diff --git a/internal/stores/data_style/model/lines/common.js b/internal/stores/data_style/model/lines/common.js index d64fd062..4576a645 100644 --- a/internal/stores/data_style/model/lines/common.js +++ b/internal/stores/data_style/model/lines/common.js @@ -1,8 +1,10 @@ import merge from "lodash/merge"; import { useDataStyleState } from "@ogw_internal/stores/data_style/state"; +import { useModelCommonStyle } from "@ogw_internal/stores/data_style/model/common"; export function useModelLinesCommonStyle() { const dataStyleState = useDataStyleState(); + const modelCommonStyle = useModelCommonStyle(); function modelLinesStyle(id) { return dataStyleState.getStyle(id).lines; @@ -14,12 +16,12 @@ export function useModelLinesCommonStyle() { return merge({}, groupStyle, individualStyle); } - function mutateModelLinesStyle(id, line_ids, values) { - return dataStyleState.mutateComponentStyles(id, line_ids, values); + function mutateModelLinesStyle(id, lines_ids, values) { + return modelCommonStyle.mutateComponentStyles(id, lines_ids, values); } function mutateModelLineStyle(id, line_id, values) { - return dataStyleState.mutateComponentStyle(id, line_id, values); + return modelCommonStyle.mutateComponentStyle(id, line_id, values); } return { diff --git a/internal/stores/data_style/model/lines/index.js b/internal/stores/data_style/model/lines/index.js index d6913bb6..97913ddd 100644 --- a/internal/stores/data_style/model/lines/index.js +++ b/internal/stores/data_style/model/lines/index.js @@ -1,8 +1,7 @@ -// Local imports import { useDataStore } from "@ogw_front/stores/data"; -import { useModelLinesColorStyle } from "./color"; +import { useModelLinesColor } from "./color"; import { useModelLinesCommonStyle } from "./common"; -import { useModelLinesVisibilityStyle } from "./visibility"; +import { useModelLinesVisibility } from "./visibility"; async function setModelLinesDefaultStyle(_id) { // Placeholder @@ -10,44 +9,44 @@ async function setModelLinesDefaultStyle(_id) { export function useModelLinesStyle() { const dataStore = useDataStore(); - const modelLinesCommonStyle = useModelLinesCommonStyle(); - const modelLinesVisibilityStyle = useModelLinesVisibilityStyle(); - const modelLinesColorStyle = useModelLinesColorStyle(); + const commonStyle = useModelLinesCommonStyle(); + const visibilityStyle = useModelLinesVisibility(); + const colorStyle = useModelLinesColor(); - async function applyModelLinesStyle(id) { - const line_ids = await dataStore.getLinesGeodeIds(id); - if (line_ids.length === 0) { + async function applyModelLinesStyle(modelId) { + const lines_ids = await dataStore.getLinesGeodeIds(modelId); + if (!lines_ids?.length) { return; } const visibilityGroups = {}; const colorGroups = {}; - for (const line_id of line_ids) { - const style = modelLinesCommonStyle.modelLineStyle(id, line_id); + for (const line_id of lines_ids) { + const style = commonStyle.modelLineStyle(modelId, line_id); - const vKey = String(style.visibility); - if (!visibilityGroups[vKey]) { - visibilityGroups[vKey] = []; + const visibility = String(style.visibility); + if (!visibilityGroups[visibility]) { + visibilityGroups[visibility] = []; } - visibilityGroups[vKey].push(line_id); + visibilityGroups[visibility].push(line_id); - const cKey = JSON.stringify(style.color); - if (!colorGroups[cKey]) { - colorGroups[cKey] = []; + const color_mode = style.color_mode || "constant"; + const color_key = color_mode === "random" ? "random" : JSON.stringify(style.color); + if (!colorGroups[color_key]) { + colorGroups[color_key] = { color_mode, color: style.color, lines_ids: [] }; } - colorGroups[cKey].push(line_id); + colorGroups[color_key].lines_ids.push(line_id); } - const promises = []; - - for (const [vValue, ids] of Object.entries(visibilityGroups)) { - promises.push(modelLinesVisibilityStyle.setModelLinesVisibility(id, ids, vValue === "true")); - } - - for (const [cValue, ids] of Object.entries(colorGroups)) { - promises.push(modelLinesColorStyle.setModelLinesColor(id, ids, JSON.parse(cValue))); - } + const promises = [ + ...Object.entries(visibilityGroups).map(([visibility, ids]) => + visibilityStyle.setModelLinesVisibility(modelId, ids, visibility === "true"), + ), + ...Object.values(colorGroups).map(({ color_mode, color, lines_ids: ids }) => + colorStyle.setModelLinesColor(modelId, ids, color, color_mode), + ), + ]; return Promise.all(promises); } @@ -55,8 +54,8 @@ export function useModelLinesStyle() { return { applyModelLinesStyle, setModelLinesDefaultStyle, - ...modelLinesCommonStyle, - ...modelLinesVisibilityStyle, - ...modelLinesColorStyle, + ...commonStyle, + ...visibilityStyle, + ...colorStyle, }; } diff --git a/internal/stores/data_style/model/lines/visibility.js b/internal/stores/data_style/model/lines/visibility.js index 12cbdbb7..29f84d50 100644 --- a/internal/stores/data_style/model/lines/visibility.js +++ b/internal/stores/data_style/model/lines/visibility.js @@ -1,47 +1,20 @@ -// Third party imports -import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json"; - -// Local imports -import { useDataStore } from "@ogw_front/stores/data"; +import { useModelCommonStyle } from "@ogw_internal/stores/data_style/model/common"; import { useModelLinesCommonStyle } from "./common"; -import { useViewerStore } from "@ogw_front/stores/viewer"; +import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json"; -// Local constants -const model_lines_schemas = viewer_schemas.opengeodeweb_viewer.model.lines; +const schema = viewer_schemas.opengeodeweb_viewer.model.lines.visibility; -export function useModelLinesVisibilityStyle() { - const dataStore = useDataStore(); - const viewerStore = useViewerStore(); +export function useModelLinesVisibility() { + const modelCommonStyle = useModelCommonStyle(); const modelLinesCommonStyle = useModelLinesCommonStyle(); + function modelLineVisibility(id, line_id) { return modelLinesCommonStyle.modelLineStyle(id, line_id).visibility; } - function setModelLinesVisibility(id, line_ids, visibility) { - if (!line_ids || line_ids.length === 0) { - return Promise.resolve(); - } - return dataStore.getMeshComponentsViewerIds(id, line_ids).then((line_viewer_ids) => { - if (!line_viewer_ids || line_viewer_ids.length === 0) { - return modelLinesCommonStyle.mutateModelLinesStyle(id, line_ids, { - visibility, - }); - } - return viewerStore.request( - model_lines_schemas.visibility, - { id, block_ids: line_viewer_ids, visibility }, - { - response_function: () => - modelLinesCommonStyle.mutateModelLinesStyle(id, line_ids, { - visibility, - }), - }, - ); - }); + function setModelLinesVisibility(modelId, lines_ids, visibility) { + return modelCommonStyle.setModelTypeVisibility(modelId, lines_ids, visibility, schema); } - return { - modelLineVisibility, - setModelLinesVisibility, - }; + return { setModelLinesVisibility, modelLineVisibility }; } diff --git a/internal/stores/data_style/model/selection.js b/internal/stores/data_style/model/selection.js new file mode 100644 index 00000000..f8020341 --- /dev/null +++ b/internal/stores/data_style/model/selection.js @@ -0,0 +1,83 @@ +import { MESH_TYPES } from "@ogw_front/utils/default_styles"; +import { database } from "@ogw_internal/database/database"; +import { liveQuery } from "dexie"; + +function buildSelection(modelId, components, stylesMap, typeStylesMap, dataStyleState) { + const componentsByType = Object.fromEntries( + MESH_TYPES.map((componentType) => [componentType, []]), + ); + for (const component of components) { + if (componentsByType[component.type]) { + componentsByType[component.type].push(component); + } + } + + const groupStyles = dataStyleState.getStyle(modelId); + const selection = []; + for (const componentType of MESH_TYPES) { + const typeComponents = componentsByType[componentType]; + if (typeComponents.length === 0) { + continue; + } + + const typeKey = `${componentType.toLowerCase()}s`; + const typeStyle = typeStylesMap[componentType]; + const defaultVisibility = typeStyle?.visibility ?? groupStyles[typeKey]?.visibility ?? true; + + let allVisible = true; + for (const component of typeComponents) { + const isVisible = stylesMap[component.geode_id]?.visibility ?? defaultVisibility; + if (isVisible) { + selection.push(component.geode_id); + } else { + allVisible = false; + } + } + if (allVisible) { + selection.push(componentType); + } + } + return selection; +} + +function useModelSelection(id_ref, dataStyleState) { + const selection = ref([]); + watch( + () => unref(id_ref), + (modelId, _prev, onCleanup) => { + if (!modelId) { + selection.value = []; + return; + } + const observable = liveQuery(async () => { + const [allComponents, componentStyles, typeStyles] = await Promise.all([ + database.model_components.where("id").equals(modelId).toArray(), + database.model_component_datastyle.where("id_model").equals(modelId).toArray(), + database.model_component_type_datastyle.where("id_model").equals(modelId).toArray(), + ]); + + if (allComponents.length === 0) { + return []; + } + + const stylesMap = Object.fromEntries( + componentStyles.map((style) => [style.id_component, style]), + ); + const typeStylesMap = Object.fromEntries(typeStyles.map((style) => [style.type, style])); + + return buildSelection(modelId, allComponents, stylesMap, typeStylesMap, dataStyleState); + }); + + const subscription = observable.subscribe({ + next: (val) => { + selection.value = val; + }, + }); + onCleanup(() => subscription.unsubscribe()); + }, + { immediate: true }, + ); + return selection; +} + +export { buildSelection, useModelSelection }; diff --git a/internal/stores/data_style/model/surfaces/color.js b/internal/stores/data_style/model/surfaces/color.js index 449ac106..f76cd4e8 100644 --- a/internal/stores/data_style/model/surfaces/color.js +++ b/internal/stores/data_style/model/surfaces/color.js @@ -1,44 +1,20 @@ -// Third party imports -import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json"; - -// Local imports -import { useDataStore } from "@ogw_front/stores/data"; +import { useModelCommonStyle } from "@ogw_internal/stores/data_style/model/common"; import { useModelSurfacesCommonStyle } from "./common"; -import { useViewerStore } from "@ogw_front/stores/viewer"; +import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json"; -// Local constants -const model_surfaces_schemas = viewer_schemas.opengeodeweb_viewer.model.surfaces; +const schema = viewer_schemas.opengeodeweb_viewer.model.surfaces.color; -export function useModelSurfacesColorStyle() { - const dataStore = useDataStore(); - const viewerStore = useViewerStore(); +export function useModelSurfacesColor() { + const modelCommonStyle = useModelCommonStyle(); const modelSurfacesCommonStyle = useModelSurfacesCommonStyle(); function modelSurfaceColor(id, surface_id) { return modelSurfacesCommonStyle.modelSurfaceStyle(id, surface_id).color; } - function setModelSurfacesColor(id, surface_ids, color) { - if (!surface_ids || surface_ids.length === 0) { - return Promise.resolve(); - } - return dataStore.getMeshComponentsViewerIds(id, surface_ids).then((surface_viewer_ids) => { - if (!surface_viewer_ids || surface_viewer_ids.length === 0) { - return modelSurfacesCommonStyle.mutateModelSurfacesStyle(id, surface_ids, { color }); - } - return viewerStore.request( - model_surfaces_schemas.color, - { id, block_ids: surface_viewer_ids, color }, - { - response_function: () => - modelSurfacesCommonStyle.mutateModelSurfacesStyle(id, surface_ids, { color }), - }, - ); - }); + function setModelSurfacesColor(modelId, surfaces_ids, color, color_mode = "constant") { + return modelCommonStyle.setModelTypeColor(modelId, surfaces_ids, color, schema, color_mode); } - return { - modelSurfaceColor, - setModelSurfacesColor, - }; + return { setModelSurfacesColor, modelSurfaceColor }; } diff --git a/internal/stores/data_style/model/surfaces/common.js b/internal/stores/data_style/model/surfaces/common.js index 15cb84da..5fc3e229 100644 --- a/internal/stores/data_style/model/surfaces/common.js +++ b/internal/stores/data_style/model/surfaces/common.js @@ -1,8 +1,10 @@ import merge from "lodash/merge"; import { useDataStyleState } from "@ogw_internal/stores/data_style/state"; +import { useModelCommonStyle } from "@ogw_internal/stores/data_style/model/common"; export function useModelSurfacesCommonStyle() { const dataStyleState = useDataStyleState(); + const modelCommonStyle = useModelCommonStyle(); function modelSurfacesStyle(id) { return dataStyleState.getStyle(id).surfaces; @@ -14,12 +16,12 @@ export function useModelSurfacesCommonStyle() { return merge({}, groupStyle, individualStyle); } - function mutateModelSurfacesStyle(id, surface_ids, values) { - return dataStyleState.mutateComponentStyles(id, surface_ids, values); + function mutateModelSurfacesStyle(id, surfaces_ids, values) { + return modelCommonStyle.mutateComponentStyles(id, surfaces_ids, values); } function mutateModelSurfaceStyle(id, surface_id, values) { - return dataStyleState.mutateComponentStyle(id, surface_id, values); + return modelCommonStyle.mutateComponentStyle(id, surface_id, values); } return { diff --git a/internal/stores/data_style/model/surfaces/index.js b/internal/stores/data_style/model/surfaces/index.js index 42014b67..c533ef99 100644 --- a/internal/stores/data_style/model/surfaces/index.js +++ b/internal/stores/data_style/model/surfaces/index.js @@ -1,8 +1,7 @@ -// Local imports import { useDataStore } from "@ogw_front/stores/data"; -import { useModelSurfacesColorStyle } from "./color"; +import { useModelSurfacesColor } from "./color"; import { useModelSurfacesCommonStyle } from "./common"; -import { useModelSurfacesVisibilityStyle } from "./visibility"; +import { useModelSurfacesVisibility } from "./visibility"; async function setModelSurfacesDefaultStyle(_id) { // Placeholder @@ -10,46 +9,44 @@ async function setModelSurfacesDefaultStyle(_id) { export function useModelSurfacesStyle() { const dataStore = useDataStore(); - const modelSurfacesCommonStyle = useModelSurfacesCommonStyle(); - const modelSurfacesVisibilityStyle = useModelSurfacesVisibilityStyle(); - const modelSurfacesColorStyle = useModelSurfacesColorStyle(); + const commonStyle = useModelSurfacesCommonStyle(); + const visibilityStyle = useModelSurfacesVisibility(); + const colorStyle = useModelSurfacesColor(); - async function applyModelSurfacesStyle(id) { - const surface_ids = await dataStore.getSurfacesGeodeIds(id); - if (surface_ids.length === 0) { + async function applyModelSurfacesStyle(modelId) { + const surfaces_ids = await dataStore.getSurfacesGeodeIds(modelId); + if (!surfaces_ids?.length) { return; } const visibilityGroups = {}; const colorGroups = {}; - for (const surface_id of surface_ids) { - const style = modelSurfacesCommonStyle.modelSurfaceStyle(id, surface_id); + for (const surfaces_id of surfaces_ids) { + const style = commonStyle.modelSurfaceStyle(modelId, surfaces_id); - const vKey = String(style.visibility); - if (!visibilityGroups[vKey]) { - visibilityGroups[vKey] = []; + const visibility = String(style.visibility); + if (!visibilityGroups[visibility]) { + visibilityGroups[visibility] = []; } - visibilityGroups[vKey].push(surface_id); + visibilityGroups[visibility].push(surfaces_id); - const cKey = JSON.stringify(style.color); - if (!colorGroups[cKey]) { - colorGroups[cKey] = []; + const color_mode = style.color_mode || "constant"; + const color_key = color_mode === "random" ? "random" : JSON.stringify(style.color); + if (!colorGroups[color_key]) { + colorGroups[color_key] = { color_mode, color: style.color, surfaces_ids: [] }; } - colorGroups[cKey].push(surface_id); + colorGroups[color_key].surfaces_ids.push(surfaces_id); } - const promises = []; - - for (const [vValue, ids] of Object.entries(visibilityGroups)) { - promises.push( - modelSurfacesVisibilityStyle.setModelSurfacesVisibility(id, ids, vValue === "true"), - ); - } - - for (const [cValue, ids] of Object.entries(colorGroups)) { - promises.push(modelSurfacesColorStyle.setModelSurfacesColor(id, ids, JSON.parse(cValue))); - } + const promises = [ + ...Object.entries(visibilityGroups).map(([visibility, ids]) => + visibilityStyle.setModelSurfacesVisibility(modelId, ids, visibility === "true"), + ), + ...Object.values(colorGroups).map(({ color_mode, color, surfaces_ids: ids }) => + colorStyle.setModelSurfacesColor(modelId, ids, color, color_mode), + ), + ]; return Promise.all(promises); } @@ -57,8 +54,8 @@ export function useModelSurfacesStyle() { return { applyModelSurfacesStyle, setModelSurfacesDefaultStyle, - ...modelSurfacesCommonStyle, - ...modelSurfacesVisibilityStyle, - ...modelSurfacesColorStyle, + ...commonStyle, + ...visibilityStyle, + ...colorStyle, }; } diff --git a/internal/stores/data_style/model/surfaces/visibility.js b/internal/stores/data_style/model/surfaces/visibility.js index f1720a9b..fd644f5d 100644 --- a/internal/stores/data_style/model/surfaces/visibility.js +++ b/internal/stores/data_style/model/surfaces/visibility.js @@ -1,45 +1,20 @@ -// Third party imports -import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json"; - -// Local imports -import { useDataStore } from "@ogw_front/stores/data"; +import { useModelCommonStyle } from "@ogw_internal/stores/data_style/model/common"; import { useModelSurfacesCommonStyle } from "./common"; -import { useViewerStore } from "@ogw_front/stores/viewer"; +import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json"; -// Local constants -const model_surfaces_schemas = viewer_schemas.opengeodeweb_viewer.model.surfaces; +const schema = viewer_schemas.opengeodeweb_viewer.model.surfaces.visibility; -export function useModelSurfacesVisibilityStyle() { - const dataStore = useDataStore(); - const viewerStore = useViewerStore(); +export function useModelSurfacesVisibility() { + const modelCommonStyle = useModelCommonStyle(); const modelSurfacesCommonStyle = useModelSurfacesCommonStyle(); + function modelSurfaceVisibility(id, surface_id) { return modelSurfacesCommonStyle.modelSurfaceStyle(id, surface_id).visibility; } - function setModelSurfacesVisibility(id, surface_ids, visibility) { - if (!surface_ids || surface_ids.length === 0) { - return Promise.resolve(); - } - return dataStore.getMeshComponentsViewerIds(id, surface_ids).then((surface_viewer_ids) => { - if (!surface_viewer_ids || surface_viewer_ids.length === 0) { - return modelSurfacesCommonStyle.mutateModelSurfacesStyle(id, surface_ids, { visibility }); - } - return viewerStore.request( - model_surfaces_schemas.visibility, - { id, block_ids: surface_viewer_ids, visibility }, - { - response_function: () => - modelSurfacesCommonStyle.mutateModelSurfacesStyle(id, surface_ids, { - visibility, - }), - }, - ); - }); + function setModelSurfacesVisibility(modelId, surfaces_ids, visibility) { + return modelCommonStyle.setModelTypeVisibility(modelId, surfaces_ids, visibility, schema); } - return { - modelSurfaceVisibility, - setModelSurfacesVisibility, - }; + return { setModelSurfacesVisibility, modelSurfaceVisibility }; } diff --git a/internal/stores/data_style/model/visibility.js b/internal/stores/data_style/model/visibility.js new file mode 100644 index 00000000..5b22eca6 --- /dev/null +++ b/internal/stores/data_style/model/visibility.js @@ -0,0 +1,196 @@ +import { MESH_TYPES } from "@ogw_front/utils/default_styles"; +import { useDataStore } from "@ogw_front/stores/data"; +import { useDataStyleState } from "@ogw_internal/stores/data_style/state"; +import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer"; +import { useModelCommonStyle } from "@ogw_internal/stores/data_style/model/common"; +import { useViewerStore } from "@ogw_front/stores/viewer"; +import viewer_schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json"; + +const model_schemas = viewer_schemas.opengeodeweb_viewer.model; + +async function getModelComponentsMap(modelId) { + const dataStore = useDataStore(); + const results = await Promise.all( + MESH_TYPES.map(async (type) => { + const geodeIds = await dataStore.getMeshComponentGeodeIds(modelId, type); + return geodeIds.map((geode_id) => ({ geode_id, type })); + }), + ); + const allComponents = results.flat(); + return { + allComponents, + componentsMap: Object.fromEntries( + allComponents.map((component) => [component.geode_id, component]), + ), + }; +} + +async function dispatchToComponentTypes( + modelId, + componentIds, + action, + { componentStyleFunctions }, + ...args +) { + const { componentsMap } = await getModelComponentsMap(modelId); + + const idsByComponent = { + Block: [], + Surface: [], + Line: [], + Corner: [], + }; + + for (const id of componentIds) { + const type = componentsMap[id]?.type; + if (type && idsByComponent[type]) { + idsByComponent[type].push(id); + } + } + + const promises = []; + if (action === "Visibility") { + if (idsByComponent.Block.length > 0) { + promises.push( + componentStyleFunctions.Block.setModelBlocksVisibility( + modelId, + idsByComponent.Block, + ...args, + ), + ); + } + if (idsByComponent.Surface.length > 0) { + promises.push( + componentStyleFunctions.Surface.setModelSurfacesVisibility( + modelId, + idsByComponent.Surface, + ...args, + ), + ); + } + if (idsByComponent.Line.length > 0) { + promises.push( + componentStyleFunctions.Line.setModelLinesVisibility(modelId, idsByComponent.Line, ...args), + ); + } + if (idsByComponent.Corner.length > 0) { + promises.push( + componentStyleFunctions.Corner.setModelCornersVisibility( + modelId, + idsByComponent.Corner, + ...args, + ), + ); + } + } else if (action === "Color") { + if (idsByComponent.Block.length > 0) { + promises.push( + componentStyleFunctions.Block.setModelBlocksColor(modelId, idsByComponent.Block, ...args), + ); + } + if (idsByComponent.Surface.length > 0) { + promises.push( + componentStyleFunctions.Surface.setModelSurfacesColor( + modelId, + idsByComponent.Surface, + ...args, + ), + ); + } + if (idsByComponent.Line.length > 0) { + promises.push( + componentStyleFunctions.Line.setModelLinesColor(modelId, idsByComponent.Line, ...args), + ); + } + if (idsByComponent.Corner.length > 0) { + promises.push( + componentStyleFunctions.Corner.setModelCornersColor( + modelId, + idsByComponent.Corner, + ...args, + ), + ); + } + } + + return Promise.all(promises); +} + +function useModelVisibilityStyle(componentStyleFunctions) { + const dataStore = useDataStore(); + const dataStyleState = useDataStyleState(); + const hybridViewerStore = useHybridViewerStore(); + const viewerStore = useViewerStore(); + const modelCommonStyle = useModelCommonStyle(); + + function modelVisibility(modelId) { + return dataStyleState.getStyle(modelId).visibility; + } + + function setModelVisibility(modelId, visibility) { + return viewerStore.request( + model_schemas.visibility, + { id: modelId, visibility }, + { + response_function: async () => { + await hybridViewerStore.setVisibility(modelId, visibility); + await dataStyleState.mutateStyle(modelId, { visibility }); + return { id: modelId, visibility }; + }, + }, + ); + } + + async function setModelComponentsVisibility(modelId, componentIds, visibility) { + viewerStore.start_request(); + try { + const typeIds = componentIds.filter((id) => MESH_TYPES.includes(id)); + const individualIds = componentIds.filter((id) => !MESH_TYPES.includes(id)); + + const promises = []; + for (const typeId of typeIds) { + promises.push(setModelComponentTypeVisibility(modelId, typeId, visibility)); + } + + if (individualIds.length > 0) { + promises.push( + dispatchToComponentTypes( + modelId, + individualIds, + "Visibility", + { componentStyleFunctions }, + visibility, + ), + ); + } + return await Promise.all(promises); + } finally { + viewerStore.stop_request(); + } + } + + async function setModelComponentTypeVisibility(modelId, componentType, visibility) { + viewerStore.start_request(); + try { + await modelCommonStyle.mutateModelComponentTypeStyle(modelId, componentType, { + visibility, + }); + const idsForType = await dataStore.getMeshComponentGeodeIds(modelId, componentType); + if (idsForType.length === 0) { + return; + } + await setModelComponentsVisibility(modelId, idsForType, visibility); + } finally { + viewerStore.stop_request(); + } + } + + return { + modelVisibility, + setModelVisibility, + setModelComponentsVisibility, + setModelComponentTypeVisibility, + }; +} + +export { getModelComponentsMap, dispatchToComponentTypes, useModelVisibilityStyle }; diff --git a/internal/stores/data_style/state.js b/internal/stores/data_style/state.js index d6270f7f..62f762d0 100644 --- a/internal/stores/data_style/state.js +++ b/internal/stores/data_style/state.js @@ -33,6 +33,19 @@ export function useDataStyleState() { return selection; }); + const modelComponentTypeStyles = useObservable( + liveQuery(async () => { + const all = await database.model_component_type_datastyle.toArray(); + const accumulator = {}; + for (const style of all) { + const key = `${style.id_model}_${style.type}`; + accumulator[key] = style; + } + return accumulator; + }), + { initialValue: {} }, + ); + const componentStyles = useObservable( liveQuery(async () => { const all = await database.model_component_datastyle.toArray(); @@ -61,47 +74,27 @@ export function useDataStyleState() { return componentStyles.value[key] || {}; } - function mutateComponentStyle(id_model, id_component, values) { - return database.model_component_datastyle.get([id_model, id_component]).then((style) => { - const component_style = style || { id_model, id_component }; - merge(component_style, values); - return database.model_component_datastyle.put(structuredClone(toRaw(component_style))); - }); - } - - function mutateComponentStyles(id_model, id_components, values) { - return database.model_component_datastyle - .where("id_model") - .equals(id_model) - .toArray() - .then((all_styles) => { - const style_map = {}; - for (const style of all_styles) { - style_map[style.id_component] = style; - } - - const updates = id_components.map((id_component) => { - const style = style_map[id_component] || { id_model, id_component }; - merge(style, values); - return toRaw(style); - }); - - return database.model_component_datastyle.bulkPut(structuredClone(updates)); - }); + function getModelComponentTypeStyle(id_model, type) { + const key = `${id_model}_${type}`; + return modelComponentTypeStyles.value[key] || {}; } function clear() { - return Promise.all([database.data_style.clear(), database.model_component_datastyle.clear()]); + return Promise.all([ + database.data_style.clear(), + database.model_component_datastyle.clear(), + database.model_component_type_datastyle.clear(), + ]); } return { getStyle, - mutateStyle, getComponentStyle, - mutateComponentStyle, - mutateComponentStyles, + getModelComponentTypeStyle, + mutateStyle, styles, componentStyles, + modelComponentTypeStyles, objectVisibility, selectedObjects, clear, diff --git a/tests/integration/stores/data_style/model/blocks.nuxt.test.js b/tests/integration/stores/data_style/model/blocks.nuxt.test.js index c1bde1d5..e2349c38 100644 --- a/tests/integration/stores/data_style/model/blocks.nuxt.test.js +++ b/tests/integration/stores/data_style/model/blocks.nuxt.test.js @@ -53,7 +53,11 @@ describe("Model blocks", () => { await sleep(SLEEP_MS); expect(spy).toHaveBeenCalledWith( model_blocks_schemas.visibility, - { id, block_ids: block_viewer_ids, visibility }, + { + id, + block_ids: block_viewer_ids, + visibility, + }, { response_function: expect.any(Function), }, @@ -78,7 +82,12 @@ describe("Model blocks", () => { await sleep(SLEEP_MS); expect(spy).toHaveBeenCalledWith( model_blocks_schemas.color, - { id, block_ids: block_viewer_ids, color }, + { + id, + block_ids: block_viewer_ids, + color, + color_mode: "constant", + }, { response_function: expect.any(Function), }, diff --git a/tests/integration/stores/data_style/model/corners.nuxt.test.js b/tests/integration/stores/data_style/model/corners.nuxt.test.js index d43b54a6..c69faa22 100644 --- a/tests/integration/stores/data_style/model/corners.nuxt.test.js +++ b/tests/integration/stores/data_style/model/corners.nuxt.test.js @@ -53,7 +53,11 @@ describe("Model corners", () => { await sleep(SLEEP_MS); expect(spy).toHaveBeenCalledWith( model_corners_schemas.visibility, - { id, block_ids: corner_viewer_ids, visibility }, + { + id, + block_ids: corner_viewer_ids, + visibility, + }, { response_function: expect.any(Function), }, @@ -81,7 +85,12 @@ describe("Model corners", () => { await sleep(SLEEP_MS); expect(spy).toHaveBeenCalledWith( model_corners_schemas.color, - { id, block_ids: corner_viewer_ids, color }, + { + id, + block_ids: corner_viewer_ids, + color, + color_mode: "constant", + }, { response_function: expect.any(Function), }, diff --git a/tests/integration/stores/data_style/model/lines.nuxt.test.js b/tests/integration/stores/data_style/model/lines.nuxt.test.js index 2bcbbd89..8ab3df87 100644 --- a/tests/integration/stores/data_style/model/lines.nuxt.test.js +++ b/tests/integration/stores/data_style/model/lines.nuxt.test.js @@ -53,7 +53,11 @@ describe("Model lines", () => { await sleep(SLEEP_MS); expect(spy).toHaveBeenCalledWith( model_lines_schemas.visibility, - { id, block_ids: lines_viewer_ids, visibility }, + { + id, + block_ids: lines_viewer_ids, + visibility, + }, { response_function: expect.any(Function), }, @@ -81,7 +85,12 @@ describe("Model lines", () => { await sleep(SLEEP_MS); expect(spy).toHaveBeenCalledWith( model_lines_schemas.color, - { id, block_ids: lines_viewer_ids, color }, + { + id, + block_ids: lines_viewer_ids, + color, + color_mode: "constant", + }, { response_function: expect.any(Function), }, diff --git a/tests/integration/stores/data_style/model/surfaces.nuxt.test.js b/tests/integration/stores/data_style/model/surfaces.nuxt.test.js index af36e575..ff8caa99 100644 --- a/tests/integration/stores/data_style/model/surfaces.nuxt.test.js +++ b/tests/integration/stores/data_style/model/surfaces.nuxt.test.js @@ -52,7 +52,11 @@ describe("model surfaces", () => { await sleep(SLEEP_MS); expect(spy).toHaveBeenCalledWith( model_surfaces_schemas.visibility, - { id, block_ids: surface_viewer_ids, visibility }, + { + id, + block_ids: surface_viewer_ids, + visibility, + }, { response_function: expect.any(Function), }, @@ -80,7 +84,12 @@ describe("model surfaces", () => { await sleep(SLEEP_MS); expect(spy).toHaveBeenCalledWith( model_surfaces_schemas.color, - { id, block_ids: surface_viewer_ids, color }, + { + id, + block_ids: surface_viewer_ids, + color, + color_mode: "constant", + }, { response_function: expect.any(Function), },