389 lines
13 KiB
JavaScript
389 lines
13 KiB
JavaScript
import { Color, ColorToHexString } from '../engine/model/color.js';
|
|
import { AddDiv, AddDomElement, AddRangeSlider, AddToggle, ShowDomElement, GetDomElementOuterHeight, SetDomElementOuterHeight } from '../engine/viewer/domutils.js';
|
|
import { FeatureSet } from './featureset.js';
|
|
import { Settings, Theme } from './settings.js';
|
|
import { SidebarPanel } from './sidebarpanel.js';
|
|
|
|
export function AddColorPicker (parentDiv, defaultColor, predefinedColors, onChange)
|
|
{
|
|
let pickr = Pickr.create ({
|
|
el : parentDiv,
|
|
theme : 'monolith',
|
|
position : 'left-start',
|
|
swatches : predefinedColors,
|
|
comparison : false,
|
|
default : '#' + ColorToHexString (defaultColor),
|
|
components : {
|
|
preview : false,
|
|
opacity : false,
|
|
hue : true,
|
|
interaction: {
|
|
hex : false,
|
|
rgba : false,
|
|
hsla : false,
|
|
hsva : false,
|
|
cmyk : false,
|
|
input : true,
|
|
clear : false,
|
|
save : false
|
|
}
|
|
}
|
|
});
|
|
pickr.on ('change', (color, source, instance) => {
|
|
let rgbaColor = color.toRGBA ();
|
|
let ovColor = new Color (
|
|
parseInt (rgbaColor[0], 10),
|
|
parseInt (rgbaColor[1], 10),
|
|
parseInt (rgbaColor[2], 10)
|
|
);
|
|
onChange (ovColor);
|
|
});
|
|
return pickr;
|
|
}
|
|
|
|
export class SettingsColorSection
|
|
{
|
|
constructor (parentDiv)
|
|
{
|
|
this.parentDiv = parentDiv;
|
|
this.contentDiv = null;
|
|
this.pickr = null;
|
|
}
|
|
|
|
Init (title, description, color, predefinedColors, onChange)
|
|
{
|
|
this.contentDiv = AddDiv (this.parentDiv, 'ov_sidebar_settings_content');
|
|
let titleDiv = AddDiv (this.contentDiv, 'ov_sidebar_subtitle');
|
|
let colorInput = AddDiv (titleDiv, 'ov_color_picker');
|
|
AddDiv (titleDiv, 'ov_sidebar_subtitle', title);
|
|
this.pickr = AddColorPicker (colorInput, color, predefinedColors, (color) => {
|
|
onChange (color);
|
|
});
|
|
AddDiv (this.contentDiv, 'ov_sidebar_settings_padded', description);
|
|
}
|
|
|
|
Show (show)
|
|
{
|
|
ShowDomElement (this.contentDiv, show);
|
|
}
|
|
|
|
Update (color)
|
|
{
|
|
if (this.pickr === null) {
|
|
return;
|
|
}
|
|
this.pickr.setColor ('#' + ColorToHexString (color));
|
|
}
|
|
|
|
Clear ()
|
|
{
|
|
if (this.pickr === null) {
|
|
return;
|
|
}
|
|
this.pickr.hide ();
|
|
}
|
|
}
|
|
|
|
export class SettingsGridDisplaySection
|
|
{
|
|
constructor (parentDiv)
|
|
{
|
|
this.parentDiv = parentDiv;
|
|
this.gridDisplayToggle = null;
|
|
}
|
|
|
|
Init (showGrid, onChange)
|
|
{
|
|
let contentDiv = AddDiv (this.parentDiv, 'ov_sidebar_settings_content');
|
|
let titleDiv = AddDiv (contentDiv, 'ov_sidebar_subtitle');
|
|
|
|
this.showGridToggle = AddToggle (titleDiv, 'ov_sidebar_subtitle_toggle');
|
|
this.showGridToggle.OnChange (() => {
|
|
onChange (this.showGridToggle.GetStatus ());
|
|
});
|
|
AddDiv (titleDiv, 'ov_sidebar_subtitle_text', 'Show Grid');
|
|
this.showGridToggle.SetStatus (showGrid);
|
|
}
|
|
|
|
Update (showGrid)
|
|
{
|
|
if (this.showGridToggle === null) {
|
|
return;
|
|
}
|
|
this.showGridToggle.SetStatus (showGrid);
|
|
}
|
|
}
|
|
|
|
export class SettingsEdgeDisplaySection
|
|
{
|
|
constructor (parentDiv)
|
|
{
|
|
this.parentDiv = parentDiv;
|
|
this.edgeDisplayToggle = null;
|
|
this.pickr = null;
|
|
this.thresholdSlider = null;
|
|
this.thresholdSliderValue = null;
|
|
this.edgeSettingsDiv = null;
|
|
}
|
|
|
|
Init (showEdges, edgeColor, edgeThreshold, callbacks)
|
|
{
|
|
let contentDiv = AddDiv (this.parentDiv, 'ov_sidebar_settings_content');
|
|
let titleDiv = AddDiv (contentDiv, 'ov_sidebar_subtitle');
|
|
|
|
this.edgeDisplayToggle = AddToggle (titleDiv, 'ov_sidebar_subtitle_toggle');
|
|
AddDiv (titleDiv, 'ov_sidebar_subtitle_text', 'Show Edges');
|
|
|
|
this.edgeSettingsDiv = AddDiv (contentDiv, 'ov_sidebar_settings_padded');
|
|
this.edgeDisplayToggle.OnChange (() => {
|
|
ShowDomElement (this.edgeSettingsDiv, this.edgeDisplayToggle.GetStatus ());
|
|
callbacks.onShowEdgesChange (this.edgeDisplayToggle.GetStatus () ? true : false);
|
|
});
|
|
|
|
let edgeColorRow = AddDiv (this.edgeSettingsDiv, 'ov_sidebar_settings_row');
|
|
let predefinedEdgeColors = ['#ffffff', '#e3e3e3', '#c9c9c9', '#898989', '#5f5f5f', '#494949', '#383838', '#0f0f0f'];
|
|
|
|
let colorInput = AddDiv (edgeColorRow, 'ov_color_picker');
|
|
this.pickr = AddColorPicker (colorInput, edgeColor, predefinedEdgeColors, (color) => {
|
|
callbacks.onEdgeColorChange (color);
|
|
});
|
|
AddDiv (edgeColorRow, null, 'Edge Color');
|
|
|
|
let thresholdRow = AddDiv (this.edgeSettingsDiv, 'ov_sidebar_settings_row large');
|
|
this.thresholdSlider = AddRangeSlider (thresholdRow, 0, 90);
|
|
this.thresholdSlider.setAttribute ('title', 'Edge Angle Threshold');
|
|
this.thresholdSliderValue = AddDomElement (thresholdRow, 'span', 'ov_slider_label');
|
|
this.thresholdSlider.addEventListener ('input', () => {
|
|
this.thresholdSliderValue.innerHTML = this.thresholdSlider.value;
|
|
});
|
|
this. thresholdSlider.addEventListener ('change', () => {
|
|
callbacks.onEdgeThresholdChange (this.thresholdSlider.value);
|
|
});
|
|
this.thresholdSlider.value = edgeThreshold;
|
|
this.thresholdSliderValue.innerHTML = edgeThreshold;
|
|
|
|
this.edgeDisplayToggle.SetStatus (showEdges);
|
|
this.ShowEdgeSettings (showEdges);
|
|
}
|
|
|
|
Update (showEdges, edgeColor, edgeThreshold)
|
|
{
|
|
if (this.edgeDisplayToggle === null) {
|
|
return;
|
|
}
|
|
|
|
this.edgeDisplayToggle.SetStatus (showEdges);
|
|
this.ShowEdgeSettings (showEdges);
|
|
|
|
this.pickr.setColor ('#' + ColorToHexString (edgeColor));
|
|
this.thresholdSlider.value = edgeThreshold;
|
|
this.thresholdSliderValue.innerHTML = edgeThreshold;
|
|
}
|
|
|
|
ShowEdgeSettings (show)
|
|
{
|
|
ShowDomElement (this.edgeSettingsDiv, show);
|
|
}
|
|
|
|
Clear ()
|
|
{
|
|
if (this.pickr === null) {
|
|
return;
|
|
}
|
|
this.pickr.hide ();
|
|
}
|
|
}
|
|
|
|
export class SettingsThemeSection
|
|
{
|
|
constructor (parentDiv)
|
|
{
|
|
this.parentDiv = parentDiv;
|
|
this.darkModeToggle = null;
|
|
}
|
|
|
|
Init (themeId, onChange)
|
|
{
|
|
let contentDiv = AddDiv (this.parentDiv, 'ov_sidebar_settings_content');
|
|
let titleDiv = AddDiv (contentDiv, 'ov_sidebar_subtitle');
|
|
|
|
this.darkModeToggle = AddToggle (titleDiv, 'ov_sidebar_subtitle_toggle');
|
|
this.darkModeToggle.OnChange (() => {
|
|
onChange (this.darkModeToggle.GetStatus () ? Theme.Dark : Theme.Light);
|
|
});
|
|
AddDiv (titleDiv, 'ov_sidebar_subtitle_text', 'Dark Mode');
|
|
|
|
let isDarkMode = (themeId === Theme.Dark);
|
|
this.darkModeToggle.SetStatus (isDarkMode);
|
|
}
|
|
|
|
Update (themeId)
|
|
{
|
|
if (this.darkModeToggle === null) {
|
|
return;
|
|
}
|
|
let isDarkMode = (themeId === Theme.Dark);
|
|
this.darkModeToggle.SetStatus (isDarkMode);
|
|
}
|
|
}
|
|
|
|
export class SidebarSettingsPanel extends SidebarPanel
|
|
{
|
|
constructor (parentDiv, settings)
|
|
{
|
|
super (parentDiv);
|
|
this.settings = settings;
|
|
|
|
this.sectionsDiv = AddDiv (this.contentDiv, 'ov_sidebar_settings_sections ov_thin_scrollbar');
|
|
this.backgroundColorSection = new SettingsColorSection (this.sectionsDiv);
|
|
this.defaultColorSection = new SettingsColorSection (this.sectionsDiv);
|
|
this.gridDisplaySection = null;
|
|
if (FeatureSet.ShowGrid) {
|
|
this.gridDisplaySection = new SettingsGridDisplaySection (this.sectionsDiv);
|
|
}
|
|
this.edgeDisplaySection = new SettingsEdgeDisplaySection (this.sectionsDiv);
|
|
this.themeSection = new SettingsThemeSection (this.sectionsDiv);
|
|
|
|
this.resetToDefaultsButton = AddDiv (this.contentDiv, 'ov_button ov_sidebar_button outline', 'Reset to Default');
|
|
this.resetToDefaultsButton.addEventListener ('click', () => {
|
|
this.ResetToDefaults ();
|
|
});
|
|
}
|
|
|
|
GetName ()
|
|
{
|
|
return 'Settings';
|
|
}
|
|
|
|
GetIcon ()
|
|
{
|
|
return 'settings';
|
|
}
|
|
|
|
Clear ()
|
|
{
|
|
this.backgroundColorSection.Clear ();
|
|
this.defaultColorSection.Clear ();
|
|
this.edgeDisplaySection.Clear ();
|
|
}
|
|
|
|
Init (callbacks)
|
|
{
|
|
super.Init (callbacks);
|
|
this.backgroundColorSection.Init (
|
|
'Background Color',
|
|
'Affects only the visualization.',
|
|
this.settings.backgroundColor,
|
|
['#ffffff', '#e3e3e3', '#c9c9c9', '#898989', '#5f5f5f', '#494949', '#383838', '#0f0f0f'],
|
|
(newColor) => {
|
|
this.SetBackgroundColor (newColor, false);
|
|
}
|
|
);
|
|
this.defaultColorSection.Init (
|
|
'Default Color',
|
|
'Appears when the model doesn\'t have materials.',
|
|
this.settings.defaultColor,
|
|
['#ffffff', '#e3e3e3', '#cc3333', '#fac832', '#4caf50', '#3393bd', '#9b27b0', '#fda4b8'],
|
|
(newColor) => {
|
|
this.SetDefaultColor (newColor, false);
|
|
}
|
|
);
|
|
if (this.gridDisplaySection !== null) {
|
|
this.gridDisplaySection.Init (this.settings.showGrid, (showGrid) => {
|
|
this.settings.showGrid = showGrid;
|
|
callbacks.onGridDisplayChange ();
|
|
});
|
|
}
|
|
this.edgeDisplaySection.Init (
|
|
this.settings.showEdges,
|
|
this.settings.edgeColor,
|
|
this.settings.edgeThreshold,
|
|
{
|
|
onShowEdgesChange : (showEdges) => {
|
|
this.settings.showEdges = showEdges;
|
|
callbacks.onEdgeDisplayChange ();
|
|
},
|
|
onEdgeColorChange : (edgeColor) => {
|
|
this.settings.edgeColor = edgeColor;
|
|
callbacks.onEdgeDisplayChange ();
|
|
},
|
|
onEdgeThresholdChange : (edgeThreshold) => {
|
|
this.settings.edgeThreshold = edgeThreshold;
|
|
callbacks.onEdgeDisplayChange ();
|
|
}
|
|
}
|
|
);
|
|
this.themeSection.Init (this.settings.themeId, (themeId) => {
|
|
this.settings.themeId = themeId;
|
|
if (themeId === Theme.Light) {
|
|
this.SetBackgroundColor (new Color (255, 255, 255), true);
|
|
this.SetDefaultColor (new Color (200, 200, 200), true);
|
|
} else if (themeId === Theme.Dark) {
|
|
this.SetBackgroundColor (new Color (42, 43, 46), true);
|
|
this.SetDefaultColor (new Color (200, 200, 200), true);
|
|
}
|
|
callbacks.onThemeChange ();
|
|
});
|
|
}
|
|
|
|
UpdateSettings (hasDefaultMaterial)
|
|
{
|
|
this.defaultColorSection.Show (hasDefaultMaterial);
|
|
this.Resize ();
|
|
}
|
|
|
|
SetBackgroundColor (color, setInput)
|
|
{
|
|
this.settings.backgroundColor = color;
|
|
if (setInput) {
|
|
this.backgroundColorSection.Update (color);
|
|
} else {
|
|
this.callbacks.onBackgroundColorChange ();
|
|
}
|
|
}
|
|
|
|
SetDefaultColor (color, setInput)
|
|
{
|
|
this.settings.defaultColor = color;
|
|
if (setInput) {
|
|
this.defaultColorSection.Update (color);
|
|
} else {
|
|
this.callbacks.onDefaultColorChange ();
|
|
}
|
|
}
|
|
|
|
ResetToDefaults ()
|
|
{
|
|
let defaultSettings = new Settings ();
|
|
|
|
this.settings.backgroundColor = defaultSettings.backgroundColor;
|
|
this.settings.defaultColor = defaultSettings.defaultColor;
|
|
this.settings.showGrid = defaultSettings.showGrid;
|
|
this.settings.showEdges = defaultSettings.showEdges;
|
|
this.settings.edgeColor = defaultSettings.edgeColor;
|
|
this.settings.edgeThreshold = defaultSettings.edgeThreshold;
|
|
this.settings.themeId = defaultSettings.themeId;
|
|
|
|
this.backgroundColorSection.Update (defaultSettings.backgroundColor);
|
|
this.defaultColorSection.Update (defaultSettings.defaultColor);
|
|
if (this.gridDisplaySection !== null) {
|
|
this.gridDisplaySection.Update (defaultSettings.showGrid);
|
|
}
|
|
this.edgeDisplaySection.Update (defaultSettings.showEdges, defaultSettings.edgeColor, defaultSettings.edgeThreshold);
|
|
this.themeSection.Update (defaultSettings.themeId);
|
|
|
|
if (this.gridDisplaySection !== null) {
|
|
this.callbacks.onGridDisplayChange ();
|
|
}
|
|
this.callbacks.onThemeChange ();
|
|
}
|
|
|
|
Resize ()
|
|
{
|
|
let titleHeight = GetDomElementOuterHeight (this.titleDiv);
|
|
let resetButtonHeight = GetDomElementOuterHeight (this.resetToDefaultsButton);
|
|
let height = this.parentDiv.offsetHeight;
|
|
SetDomElementOuterHeight (this.sectionsDiv, height - titleHeight - resetButtonHeight);
|
|
}
|
|
}
|