Merge branch 'main' into dim/fe2/newsletter-registration

This commit is contained in:
Dimitrie Stefanescu 2023-06-22 15:42:21 +01:00
Родитель be4e840a80 d8afd14b71
Коммит 7962d56530
23 изменённых файлов: 1220 добавлений и 1429 удалений

Просмотреть файл

@ -14,7 +14,7 @@
<!-- Comment bubbles -->
<ViewerAnchoredPointThread
v-for="thread in Object.values(commentThreads)"
v-show="!hideBubbles || thread.isExpanded"
v-show="!hideBubbles || isOpenThread(thread.id)"
:key="thread.id"
:model-value="thread"
:class="openThread?.id === thread.id ? 'z-[12]' : 'z-[11]'"
@ -110,11 +110,14 @@ import {
useInjectedViewerInterfaceState,
useInjectedViewerState
} from '~~/lib/viewer/composables/setup'
import { useThreadUtilities } from '~~/lib/viewer/composables/ui'
const parentEl = ref(null as Nullable<HTMLElement>)
const { isLoggedIn } = useActiveUser()
const { sessionId } = useInjectedViewerState()
const { users } = useViewerUserActivityTracking({ parentEl })
const { isOpenThread, open } = useThreadUtilities()
const canPostComment = useCheckViewerCommentingAccess()
const followers = computed(() => {
@ -132,8 +135,7 @@ const {
threads: {
openThread: { thread: openThread },
items: commentThreads,
hideBubbles,
open
hideBubbles
}
} = useInjectedViewerInterfaceState()

Просмотреть файл

@ -78,8 +78,8 @@ import {
isValidCommentContentInput,
convertCommentEditorValueToInput
} from '~~/lib/viewer/helpers/comments'
import { useInjectedViewerInterfaceState } from '~~/lib/viewer/composables/setup'
import { useMixpanel } from '~~/lib/core/composables/mp'
import { useThreadUtilities } from '~~/lib/viewer/composables/ui'
const emit = defineEmits<{
(e: 'update:modelValue', v: ViewerNewThreadBubbleModel): void
@ -90,9 +90,9 @@ const props = defineProps<{
modelValue: ViewerNewThreadBubbleModel
}>()
const ui = useInjectedViewerInterfaceState()
const { onKeyDownHandler, updateIsTyping, pauseAutomaticUpdates } =
useIsTypingUpdateEmitter()
const { closeAllThreads, open } = useThreadUtilities()
const editor = ref(null as Nullable<{ openFilePicker: () => void }>)
const commentValue = ref(<CommentEditorValue>{ doc: undefined, attachments: undefined })
@ -137,7 +137,7 @@ const onSubmit = (comment?: CommentEditorValue) => {
if (!threadId) return
// switch to new thread
await ui.threads.open(threadId)
await open(threadId)
})
.finally(() => {
isPostingNewThread.value = false
@ -167,7 +167,7 @@ watch(
() => props.modelValue.isExpanded,
async (newVal) => {
if (newVal) {
await ui.threads.closeAllThreads()
await closeAllThreads()
}
commentValue.value = {
doc: undefined,

Просмотреть файл

@ -189,6 +189,7 @@ import {
} from '~~/lib/viewer/composables/serialization'
import { useDisableGlobalTextSelection } from '~~/lib/common/composables/window'
import { useMixpanel } from '~~/lib/core/composables/mp'
import { useThreadUtilities } from '~~/lib/viewer/composables/ui'
const emit = defineEmits<{
(e: 'update:modelValue', v: CommentBubbleModel): void
@ -220,6 +221,7 @@ const markThreadViewed = useMarkThreadViewed()
const { usersTyping } = useViewerThreadTypingTracking(threadId)
const { ellipsis, controls } = useAnimatingEllipsis()
const applyState = useApplySerializedState()
const { isOpenThread, open, closeAllThreads } = useThreadUtilities()
const commentsContainer = ref(null as Nullable<HTMLElement>)
const threadContainer = ref(null as Nullable<HTMLElement>)
@ -239,7 +241,7 @@ const comments = computed(() => [
// width: 320
// })
const isExpanded = computed(() => props.modelValue.isExpanded)
const isExpanded = computed(() => isOpenThread(props.modelValue.id))
const isTypingMessage = computed(() => {
if (!usersTyping.value.length) return null
@ -317,11 +319,13 @@ const threadAuthors = computed(() => {
return authors
})
const changeExpanded = (newVal: boolean) => {
emit('update:modelValue', {
...props.modelValue,
isExpanded: newVal
})
const changeExpanded = async (newVal: boolean) => {
if (newVal) {
await open(props.modelValue.id)
} else {
await closeAllThreads()
}
emit('update:expanded', newVal)
mp.track('Comment Action', {
type: 'action',

Просмотреть файл

@ -68,6 +68,7 @@ import { useArchiveComment } from '~~/lib/viewer/composables/commentManagement'
import { ToastNotificationType, useGlobalToast } from '~~/lib/common/composables/toast'
import { Roles } from '@speckle/shared'
import { useMixpanel } from '~~/lib/core/composables/mp'
import { useThreadUtilities } from '~~/lib/viewer/composables/ui'
const props = defineProps<{
thread: LoadedCommentThread
@ -75,8 +76,9 @@ const props = defineProps<{
const { resourceItems } = useInjectedViewerLoadedResources()
const {
threads: { open: openThreadRaw, openThread }
threads: { openThread }
} = useInjectedViewerInterfaceState()
const { open: openThreadRaw } = useThreadUtilities()
const mp = useMixpanel()
const open = (id: string) => {

Просмотреть файл

@ -1,14 +1,13 @@
import { CSSProperties, Ref } from 'vue'
import { Nullable, SpeckleViewer } from '@speckle/shared'
import {
InitialStateWithUrlHashState,
LoadedCommentThread,
useInjectedViewerInterfaceState,
useInjectedViewerState,
useResetUiState
} from '~~/lib/viewer/composables/setup'
import { graphql } from '~~/lib/common/generated/gql'
import { reduce, difference, debounce } from 'lodash-es'
import { debounce } from 'lodash-es'
import { Vector3 } from 'three'
import {
useOnViewerLoadComplete,
@ -22,7 +21,7 @@ import {
useResponsiveHorizontalDirectionCalculation
} from '~~/lib/common/composables/window'
import { useViewerUserActivityBroadcasting } from '~~/lib/viewer/composables/activity'
import { until, useIntervalFn } from '@vueuse/core'
import { useIntervalFn } from '@vueuse/core'
import {
StateApplyMode,
useApplySerializedState,
@ -124,7 +123,6 @@ export type CommentBubbleModel = Merge<
LoadedCommentThread,
{ viewerState: Nullable<SpeckleViewer.ViewerState.SerializedViewerState> }
> & {
isExpanded: boolean
isOccluded: boolean
style: Partial<CSSProperties> & { x?: number; y?: number }
}
@ -161,129 +159,6 @@ export function useViewerCommentBubblesProjection(params: {
})
}
export function useViewerCommentBubbles(
options?: Partial<{
state: InitialStateWithUrlHashState
}>
) {
const {
resources: {
response: { commentThreads: commentThreadsBase }
},
urlHashState: { focusedThreadId }
} = options?.state || useInjectedViewerState()
const commentThreads = ref({} as Record<string, CommentBubbleModel>)
const openThread = computed(() =>
Object.values(commentThreads.value).find(
(t) => t.isExpanded && t.id === focusedThreadId.value
)
)
useSelectionEvents(
{
singleClickCallback: (eventInfo) => {
if ((eventInfo && eventInfo?.hits.length === 0) || !eventInfo) {
// Close open thread
// Object.values(commentThreads.value).forEach((t) => (t.isExpanded = false))
}
}
},
{ state: options?.state }
)
const closeAllThreads = async () => {
await focusedThreadId.update(null)
}
const open = async (id: string) => {
if (id === focusedThreadId.value) return
await focusedThreadId.update(id)
await Promise.all([
until(focusedThreadId).toBe(id),
until(openThread).toMatch((t) => t?.id === id)
])
}
// Shallow watcher, only for mapping `commentThreadsBase` -> `commentThreads`
watch(
commentThreadsBase,
(newCommentThreads) => {
const newModels = reduce(
newCommentThreads,
(results, item) => {
const id = item.id
results[id] = {
...(commentThreads.value[id]
? commentThreads.value[id]
: {
isExpanded: false,
isOccluded: false,
style: {}
}),
...item,
isExpanded: !!(focusedThreadId.value && id === focusedThreadId.value),
viewerState: SpeckleViewer.ViewerState.isSerializedViewerState(
item.viewerState
)
? item.viewerState
: null
}
return results
},
{} as Record<string, CommentBubbleModel>
)
commentThreads.value = newModels
},
{ immediate: true }
)
// Making sure there's only ever 1 expanded thread & focusedThreadId is linked to these values
watch(
() =>
Object.values(commentThreads.value)
.filter((t) => t.isExpanded)
.map((t) => t.id),
async (newExpandedThreadIds, oldExpandedThreadIds) => {
const completelyNewIds = difference(
newExpandedThreadIds,
oldExpandedThreadIds || []
)
const finalOpenThreadId =
(completelyNewIds.length ? completelyNewIds[0] : newExpandedThreadIds[0]) ||
null
for (const commentThread of Object.values(commentThreads.value)) {
const shouldBeExpanded = commentThread.id === finalOpenThreadId
if (commentThread.isExpanded !== shouldBeExpanded) {
commentThreads.value[commentThread.id].isExpanded = shouldBeExpanded
}
}
if (focusedThreadId.value !== finalOpenThreadId) {
await focusedThreadId.update(finalOpenThreadId)
}
},
{ deep: true }
)
// Toggling isExpanded when threadIdToOpen changes
watch(focusedThreadId, (id) => {
if (id) {
if (commentThreads.value[id]) commentThreads.value[id].isExpanded = true
} else {
Object.values(commentThreads.value).forEach((t) => (t.isExpanded = false))
}
})
return {
commentThreads,
openThread,
closeAllThreads,
open
}
}
export function useViewerOpenedThreadUpdateEmitter() {
if (process.server) return

Просмотреть файл

@ -50,10 +50,7 @@ import {
} from '~~/lib/common/helpers/graphql'
import { nanoid } from 'nanoid'
import { ToastNotificationType, useGlobalToast } from '~~/lib/common/composables/toast'
import {
CommentBubbleModel,
useViewerCommentBubbles
} from '~~/lib/viewer/composables/commentBubbles'
import { CommentBubbleModel } from '~~/lib/viewer/composables/commentBubbles'
import { setupUrlHashState } from '~~/lib/viewer/composables/setup/urlHashState'
import { SpeckleObject } from '~~/lib/common/helpers/sceneExplorer'
import { Box3, Vector3 } from 'three'
@ -69,6 +66,7 @@ import {
} from '~~/lib/viewer/composables/setup/diff'
import { useDiffUtilities, useFilterUtilities } from '~~/lib/viewer/composables/ui'
import { reduce } from 'lodash-es'
import { setupViewerCommentBubbles } from '~~/lib/viewer/composables/setup/comments'
export type LoadedModel = NonNullable<
Get<ViewerLoadedResourcesQuery, 'project.models.items[0]'>
@ -224,8 +222,6 @@ export type InjectableViewerState = Readonly<{
isTyping: Ref<boolean>
newThreadEditor: Ref<boolean>
}
closeAllThreads: () => Promise<void>
open: (id: string) => Promise<void>
hideBubbles: Ref<boolean>
}
spotlightUserSessionId: Ref<Nullable<string>>
@ -803,9 +799,7 @@ function setupInterfaceState(
/**
* THREADS
*/
const { commentThreads, openThread, closeAllThreads, open } = useViewerCommentBubbles(
{ state }
)
const { commentThreads, openThread } = setupViewerCommentBubbles({ state })
const isTyping = ref(false)
const newThreadEditor = ref(false)
const hideBubbles = ref(false)
@ -837,8 +831,6 @@ function setupInterfaceState(
isTyping,
newThreadEditor
},
closeAllThreads,
open,
hideBubbles
},
camera: {

Просмотреть файл

@ -0,0 +1,77 @@
import { CommentBubbleModel } from '~~/lib/viewer/composables/commentBubbles'
import {
InitialStateWithUrlHashState,
useInjectedViewerState
} from '~~/lib/viewer/composables/setup'
import { useSelectionEvents } from '~~/lib/viewer/composables/viewer'
import { reduce } from 'lodash-es'
import { SpeckleViewer } from '@speckle/shared'
export function setupViewerCommentBubbles(
options?: Partial<{
state: InitialStateWithUrlHashState
}>
) {
const {
resources: {
response: { commentThreads: commentThreadsBase }
},
urlHashState: { focusedThreadId }
} = options?.state || useInjectedViewerState()
const commentThreads = ref({} as Record<string, CommentBubbleModel>)
const openThread = computed(() => {
const ot = Object.values(commentThreads.value).find(
(t) => t.id === focusedThreadId.value
)
return ot
})
useSelectionEvents(
{
singleClickCallback: (eventInfo) => {
if ((eventInfo && eventInfo?.hits.length === 0) || !eventInfo) {
// Close open thread
// Object.values(commentThreads.value).forEach((t) => (t.isExpanded = false))
}
}
},
{ state: options?.state }
)
// Shallow watcher, only for mapping `commentThreadsBase` -> `commentThreads`
watch(
commentThreadsBase,
(newCommentThreads) => {
const newModels = reduce(
newCommentThreads,
(results, item) => {
const id = item.id
results[id] = {
...(commentThreads.value[id]
? commentThreads.value[id]
: {
isOccluded: false,
style: {}
}),
...item,
viewerState: SpeckleViewer.ViewerState.isSerializedViewerState(
item.viewerState
)
? item.viewerState
: null
}
return results
},
{} as Record<string, CommentBubbleModel>
)
commentThreads.value = newModels
},
{ immediate: true }
)
return {
commentThreads,
openThread
}
}

Просмотреть файл

@ -0,0 +1,33 @@
import { ViewerEvent } from '@speckle/viewer'
import { useInjectedViewerState } from '~~/lib/viewer/composables/setup'
import { useViewerEventListener } from '~~/lib/viewer/composables/viewer'
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function useDebugViewerEvents() {
for (const [key, val] of Object.entries(ViewerEvent)) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
useViewerEventListener(val, (...args) => console.log(key, ...args))
}
}
function useDebugViewer() {
const state = useInjectedViewerState()
const {
viewer: { instance }
} = state
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
window.VIEWER = instance
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
window.VIEWER_STATE = () => ({ ...state })
}
export function setupDebugMode() {
if (process.server) return
if (!process.dev) return
// useDebugViewerEvents()
useDebugViewer()
}

Просмотреть файл

@ -46,6 +46,7 @@ import { areVectorsLooselyEqual } from '~~/lib/viewer/helpers/three'
import { Nullable } from '@speckle/shared'
import { useCameraUtilities } from '~~/lib/viewer/composables/ui'
import { watchTriggerable } from '@vueuse/core'
import { setupDebugMode } from '~~/lib/viewer/composables/setup/dev'
function useViewerIsBusyEventHandler() {
const state = useInjectedViewerState()
@ -696,23 +697,6 @@ function useDiffingIntegration() {
})
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function useDebugViewerEvents() {
if (process.server) return
const {
viewer: { instance }
} = useInjectedViewerState()
for (const [key, val] of Object.entries(ViewerEvent)) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
useViewerEventListener(val, (...args) => console.log(key, ...args))
}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
window.VIEWER = instance
}
export function useViewerPostSetup() {
if (process.server) return
useViewerObjectAutoLoading()
@ -727,7 +711,5 @@ export function useViewerPostSetup() {
useLightConfigIntegration()
useExplodeFactorIntegration()
useDiffingIntegration()
// test
// useDebugViewerEvents()
setupDebugMode()
}

Просмотреть файл

@ -1,6 +1,5 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import { Nullable } from '@speckle/shared'
import { SelectionEvent } from '@speckle/viewer'
import { SpeckleObject } from '~~/lib/common/helpers/sceneExplorer'
import { useMixpanel } from '~~/lib/core/composables/mp'
import { useInjectedViewerState } from '~~/lib/viewer/composables/setup'
@ -12,11 +11,11 @@ function useCollectSelection() {
ui: { selection }
} = useInjectedViewerState()
const selectionCallback = (event: Nullable<SelectionEvent>) => {
if (!event) return (selection.value = null) // reset selection location
const firstHit = event.hits[0]
selection.value = firstHit.point
const selectionCallback: Parameters<
typeof useSelectionEvents
>[0]['singleClickCallback'] = (_event, { firstVisibleSelectionHit }) => {
if (!firstVisibleSelectionHit) return (selection.value = null) // reset selection location
selection.value = firstVisibleSelectionHit.point
}
useSelectionEvents({
singleClickCallback: selectionCallback,

Просмотреть файл

@ -311,3 +311,31 @@ export function useDiffUtilities() {
areDiffsEqual
}
}
export function useThreadUtilities() {
const {
urlHashState: { focusedThreadId },
ui: {
threads: {
openThread: { thread: openThread }
}
}
} = useInjectedViewerState()
const isOpenThread = (id: string) => focusedThreadId.value === id
const closeAllThreads = async () => {
await focusedThreadId.update(null)
}
const open = async (id: string) => {
if (id === focusedThreadId.value) return
await focusedThreadId.update(id)
await Promise.all([
until(focusedThreadId).toBe(id),
until(openThread).toMatch((t) => t?.id === id)
])
}
return { closeAllThreads, open, isOpenThread }
}

Просмотреть файл

@ -21,7 +21,7 @@
</div>
<OnboardingDialogManager
v-show="showManagerDownloadDialog"
v-model:open="showManagerDownloadDialog"
@done="showManagerDownloadDialog = false"
@cancel="showManagerDownloadDialog = false"
></OnboardingDialogManager>

Просмотреть файл

@ -0,0 +1,6 @@
export default defineNuxtPlugin(() => {
if (!process.dev) return
if (!process.client) return
console.debug('🚧 Running FE2 in dev mode, extra debugging tools may be available...')
})

Просмотреть файл

@ -526,4 +526,6 @@ onMounted(() => {
triggerSearch()
}
})
defineExpose({ triggerSearch })
</script>

Просмотреть файл

@ -109,7 +109,7 @@ const getStream = () => {
// prettier-ignore
// 'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8?c=%5B-7.66134,10.82932,6.41935,-0.07739,-13.88552,1.8697,0,1%5D'
// Revit sample house (good for bim-like stuff with many display meshes)
// 'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8'
'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8'
// 'https://latest.speckle.dev/streams/c1faab5c62/commits/6c6e43e5f3'
// 'https://latest.speckle.dev/streams/58b5648c4d/commits/60371ecb2d'
// 'Super' heavy revit shit
@ -270,10 +270,11 @@ const getStream = () => {
// 'https://latest.speckle.dev/streams/c1faab5c62/objects/d3466547df9df86397eb4dff7ac9713f'
// 'https://latest.speckle.dev/streams/c1faab5c62/commits/140c443886'
// 'https://latest.speckle.dev/streams/e258b0e8db/commits/108971810d'
// 'https://latest.speckle.dev/streams/e258b0e8db/objects/3fcd63d80cf791c3f554a795846e62f6'
// 'https://latest.speckle.dev/streams/55cc1cbf0a/objects/d7ae178fb6a7b1f599a177486e14f9a6'
// 'https://latest.speckle.dev/streams/e258b0e8db/objects/3fcd63d80cf791c3f554a795846e62f6'
// 'https://latest.speckle.dev/streams/92b620fb17/commits/6adbcfa8dc'
'https://latest.speckle.dev/streams/92b620fb17/commits/6adbcfa8dc'
// 'https://latest.speckle.dev/streams/92b620fb17/commits/6adbcfa8dc'
)
}

Просмотреть файл

@ -164,12 +164,18 @@ export interface IViewer {
transition?: boolean
)
loadObject(url: string, token?: string, enableCaching?: boolean): Promise<void>
loadObject(
url: string,
token?: string,
enableCaching?: boolean,
zoomToObject?: boolean
): Promise<void>
loadObjectAsync(
url: string,
token?: string,
enableCaching?: boolean,
priority?: number
priority?: number,
zoomToObject?: boolean
): Promise<void>
cancelLoad(url: string, unload?: boolean): Promise<void>
unloadObject(url: string): Promise<void>

Просмотреть файл

@ -520,7 +520,11 @@ export default class SpeckleRenderer {
this._needsRender = true
}
public async addRenderTreeAsync(subtreeId: string, priority = 1) {
public async addRenderTreeAsync(
subtreeId: string,
priority = 1,
zoomToObject = true
) {
this.cancel[subtreeId] = false
const subtreeGroup = new Group()
subtreeGroup.name = subtreeId
@ -537,11 +541,9 @@ export default class SpeckleRenderer {
if (!batch) continue
this.addBatch(batch, subtreeGroup)
this.zoom()
if (zoomToObject) this.zoom()
if (batch.geometryType === GeometryType.MESH) {
this.updateDirectLights()
/** Updating the shadowcatcher after each batch is a bit too much. Stalls a lot */
// this.updateShadowCatcher()
}
this._needsRender = true
if (this.cancel[subtreeId]) {
@ -1176,6 +1178,7 @@ export default class SpeckleRenderer {
view.view.target['z'],
transition
)
this.viewer.cameraHandler.enableRotations()
}
/**
@ -1191,12 +1194,14 @@ export default class SpeckleRenderer {
switch (side) {
case 'front':
this.zoomExtents()
this.viewer.cameraHandler.controls.rotateTo(0, DEG90, transition)
if (this.viewer.cameraHandler.activeCam.name === 'ortho')
this.viewer.cameraHandler.disableRotations()
break
case 'back':
this.zoomExtents()
this.viewer.cameraHandler.controls.rotateTo(DEG180, DEG90, transition)
if (this.viewer.cameraHandler.activeCam.name === 'ortho')
this.viewer.cameraHandler.disableRotations()
@ -1204,6 +1209,7 @@ export default class SpeckleRenderer {
case 'up':
case 'top':
this.zoomExtents()
this.viewer.cameraHandler.controls.rotateTo(0, 0, transition)
if (this.viewer.cameraHandler.activeCam.name === 'ortho')
this.viewer.cameraHandler.disableRotations()
@ -1211,18 +1217,21 @@ export default class SpeckleRenderer {
case 'down':
case 'bottom':
this.zoomExtents()
this.viewer.cameraHandler.controls.rotateTo(0, DEG180, transition)
if (this.viewer.cameraHandler.activeCam.name === 'ortho')
this.viewer.cameraHandler.disableRotations()
break
case 'right':
this.zoomExtents()
this.viewer.cameraHandler.controls.rotateTo(DEG90, DEG90, transition)
if (this.viewer.cameraHandler.activeCam.name === 'ortho')
this.viewer.cameraHandler.disableRotations()
break
case 'left':
this.zoomExtents()
this.viewer.cameraHandler.controls.rotateTo(-DEG90, DEG90, transition)
if (this.viewer.cameraHandler.activeCam.name === 'ortho')
this.viewer.cameraHandler.disableRotations()
@ -1261,10 +1270,12 @@ export default class SpeckleRenderer {
view.target.z,
transition
)
this.viewer.cameraHandler.enableRotations()
}
private setViewPolar(view: PolarView, transition = true) {
this.viewer.cameraHandler.controls.rotate(view.azimuth, view.polar, transition)
this.viewer.cameraHandler.enableRotations()
}
public screenToNDC(

Просмотреть файл

@ -467,7 +467,12 @@ export class Viewer extends EventEmitter implements IViewer {
await loader.load()
}
public async loadObject(url: string, token: string = null, enableCaching = true) {
public async loadObject(
url: string,
token: string = null,
enableCaching = true,
zoomToObject = true
) {
if (++this.inProgressOperations === 1)
(this as EventEmitter).emit(ViewerEvent.Busy, true)
await this.downloadObject(url, token, enableCaching)
@ -480,7 +485,8 @@ export class Viewer extends EventEmitter implements IViewer {
await this.speckleRenderer.addRenderTree(url)
Logger.log('SYNC batch build time -> ', performance.now() - t0)
this.zoom()
if (zoomToObject) this.zoom()
this.speckleRenderer.resetPipeline(true)
this.emit(ViewerEvent.LoadComplete, url)
this.loaders[url].dispose()
@ -493,7 +499,8 @@ export class Viewer extends EventEmitter implements IViewer {
url: string,
token: string = null,
enableCaching = true,
priority = 1
priority = 1,
zoomToObject = true
) {
if (++this.inProgressOperations === 1)
(this as EventEmitter).emit(ViewerEvent.Busy, true)
@ -505,7 +512,7 @@ export class Viewer extends EventEmitter implements IViewer {
if (treeBuilt) {
t0 = performance.now()
await this.speckleRenderer.addRenderTreeAsync(url, priority)
await this.speckleRenderer.addRenderTreeAsync(url, priority, zoomToObject)
Logger.log('ASYNC batch build time -> ', performance.now() - t0)
this.speckleRenderer.resetPipeline(true)
this.emit(ViewerEvent.LoadComplete, url)

Просмотреть файл

@ -118,10 +118,9 @@ export default class CameraHandler {
const lineOfSight = new THREE.Vector3()
this.camera.getWorldDirection(lineOfSight)
const target = new THREE.Vector3()
this.controls.getTarget(target)
const target = new THREE.Vector3().copy(this.viewer.World.worldOrigin)
const distance = target.clone().sub(this.camera.position)
const depth = distance.dot(lineOfSight)
const depth = distance.length()
const dims = {
x: this.viewer.container.offsetWidth,
y: this.viewer.container.offsetHeight
@ -141,21 +140,22 @@ export default class CameraHandler {
this.orthoCamera.updateProjectionMatrix()
this.orthoCamera.position.copy(this.camera.position)
this.orthoCamera.quaternion.copy(this.camera.quaternion)
this.orthoCamera.updateProjectionMatrix()
this.controls.camera = this.orthoCamera
// fit the camera inside, so we don't have clipping plane issues.
// WIP implementation
const camPos = this.orthoCamera.position
const box = new THREE.Box3().setFromObject(this.viewer.speckleRenderer.allObjects)
const sphere = new THREE.Sphere()
box.getBoundingSphere(sphere)
// const camPos = this.orthoCamera.position
// const box = new THREE.Box3().setFromObject(this.viewer.speckleRenderer.allObjects)
// const sphere = new THREE.Sphere()
// box.getBoundingSphere(sphere)
let dist = sphere.distanceToPoint(camPos)
if (dist < 0) {
dist *= -1
this.controls.setPosition(camPos.x + dist, camPos.y + dist, camPos.z + dist)
}
// let dist = sphere.distanceToPoint(camPos)
// if (dist < 0) {
// dist *= -1
// this.controls.setPosition(camPos.x + dist, camPos.y + dist, camPos.z + dist)
// }
this.viewer.emit('projection-change', 'ortho')
}
@ -165,7 +165,7 @@ export default class CameraHandler {
this.camera.position.copy(this.orthoCamera.position)
this.camera.quaternion.copy(this.orthoCamera.quaternion)
this.camera.updateProjectionMatrix()
this.controls.distance = this.previousDistance
// this.controls.distance = this.previousDistance
this.controls.camera = this.camera
this.controls.zoomTo(1)
this.enableRotations()

Просмотреть файл

@ -586,7 +586,7 @@ export class FilteringManager extends EventEmitter {
const allIds: string[] = []
const key = objectIds.join(',')
if (this.idCache[key]) return this.idCache[key]
if (this.idCache[key] && this.idCache[key].length) return this.idCache[key]
this.WTI.walk((node: TreeNode) => {
if (objectIds.includes(node.model.raw.id) && node.model.raw.__closure) {

Просмотреть файл

@ -47,6 +47,7 @@ export class SpeckleCameraControls extends CameraControls {
private _didZoom = false
private overrideDollyLerpRatio = 0
private overrideZoomLerpRatio = 0
static install() {
_v3A = new Vector3()
_v3B = new Vector3()
@ -101,6 +102,10 @@ export class SpeckleCameraControls extends CameraControls {
protected _zoomInternal = (delta: number, x: number, y: number): void => {
const zoomScale = Math.pow(0.95, delta * this.dollySpeed)
/** We need to move the camera as well when zooming in orthographic mode */
const dollyScale = Math.pow(0.95, -delta * this.dollySpeed)
const distance = this._sphericalEnd.radius * dollyScale
this.dollyTo(distance, true, 0.9)
// for both PerspectiveCamera and OrthographicCamera
this.zoomTo(this._zoom * zoomScale, false, 1)

Просмотреть файл

@ -9,8 +9,8 @@ metadata:
{{- if .Values.cert_manager_issuer }}
cert-manager.io/cluster-issuer: {{ .Values.cert_manager_issuer }}
{{- end }}
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
nginx.org/client-max-body-size: "100m"
nginx.ingress.kubernetes.io/proxy-body-size: {{ (printf "%dm" (int .Values.file_size_limit_mb)) | quote }}
nginx.org/client-max-body-size: {{ (printf "%dm" (int .Values.file_size_limit_mb)) | quote }}
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
ingressClassName: nginx

2201
yarn.lock

Разница между файлами не показана из-за своего большого размера Загрузить разницу