-
Notifications
You must be signed in to change notification settings - Fork 15
Plan2D #247
base: main
Are you sure you want to change the base?
Plan2D #247
Conversation
WalkthroughThe pull request introduces several updates across multiple files in the Changes
Possibly related PRs
Suggested reviewers
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 14
🧹 Outside diff range and nitpick comments (8)
src/vim-loader/progressive/instancedSubmesh.ts (1)
11-11
: LGTM! Consider adding a brief comment for clarity.The addition of the
readonly merged = false
property is a good refactoring choice. It simplifies the code while maintaining the same behavior as the previous getter method.Consider adding a brief comment to explain the purpose of this property, for example:
/** Indicates whether this submesh is merged. Always false for InstancedSubmesh. */ readonly merged = falseThis would help future developers understand the intent and invariant nature of this property.
src/vim-webgl-viewer/gizmos/gizmos.ts (2)
73-73
: LGTM: Plans2D initialization in constructorThe
Plans2D
instance is correctly initialized in the constructor.Consider adding a brief comment explaining the purpose of
Plans2D
for better code documentation, similar to other properties in this class. For example:/** * The 2D plans gizmo for [brief explanation of its purpose]. */ readonly plans: Plans2D
Line range hint
82-92
: Update dispose method to include new Plans2D instanceThe
dispose
method should be updated to include cleanup for the newplans
property. This ensures proper resource management when theGizmos
instance is no longer needed.Consider updating the
dispose
method as follows:dispose () { this.viewer.viewport.canvas.parentElement?.removeChild(this.axes.canvas) this._measure.clear() this.section.dispose() this.loading.dispose() this.orbit.dispose() this.rectangle.dispose() this.axes.dispose() this.plans.dispose() // Add this line }Note: This assumes that
Plans2D
has adispose
method. If it doesn't, you may need to implement one or handle cleanup differently based on thePlans2D
implementation.src/vim-loader/colorAttributes.ts (1)
104-106
: LGTM: Special handling forSimpleMesh
added, but documentation needed.The addition of special handling for
SimpleMesh
instances is consistent with the changes described in the summary. However, it would be beneficial to add a comment explaining whySimpleMesh
instances are treated differently in this context.Consider adding a comment above the new conditional block to explain the rationale behind this special case, such as:
// SimpleMesh instances do not require color resetting as they handle colors differently if (sub instanceof SimpleMesh) { return }src/vim-webgl-viewer/gizmos/plans2D.ts (1)
82-82
: SetcrossOrigin
conditionally based on the image sourceSetting
image.crossOrigin = 'anonymous'
may cause issues if the image is served from the same origin and doesn't require CORS handling. Consider setting it conditionally or providing guidance on when it should be set.Apply this diff:
- image.crossOrigin = 'anonymous' // Use this if loading images from a different origin + // Set crossOrigin only if loading images from a different origin + if (shouldUseCrossOrigin(imageUrl)) { + image.crossOrigin = 'anonymous' + }And define the
shouldUseCrossOrigin
function based on your application's logic.src/vim-webgl-viewer/gizmos/plan2D.ts (2)
230-234
: Avoid using the non-null assertion operator to handle potential null values.In the
getBoundingBox()
method, using the non-null assertion operator!
assumes thatboundingBox
is always defined after computation. It's safer to handle possiblenull
orundefined
values explicitly to prevent potential runtime errors.Modify the return statement to handle undefined
boundingBox
:return this.mesh.geometry.boundingBox! + return this.mesh.geometry.boundingBox || new THREE.Box3()
98-100
: Consider making the initial gizmo mode configurable.The gizmo is initially set to 'translate' mode. Depending on user requirements, it might be beneficial to allow the initial mode to be configurable or align with user preferences.
Provide an option to set the initial gizmo mode:
constructor (viewer: Viewer, canvas: HTMLCanvasElement, initialMode: 'translate' | 'rotate' | 'scale' = 'translate') { // ... existing code ... // Enable interaction modes - gizmo.setMode('translate') // Can be 'translate', 'rotate', or 'scale' + gizmo.setMode(initialMode)This change allows the initial gizmo mode to be specified when creating an instance of
Plan2D
.src/vim-webgl-viewer/camera/camera.ts (1)
118-121
: Combine sentences in the comment for clarityThe comment for
freeze
can be made clearer by combining the sentences into one.Apply this diff to improve the comment:
/** - * Immediately stops the camera movement. And prevents any further movement until set to false. + * Immediately stops the camera movement and prevents any further movement until set to false. */ freeze: boolean
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (13)
- package.json (1 hunks)
- src/main.ts (2 hunks)
- src/vim-loader/colorAttributes.ts (2 hunks)
- src/vim-loader/mesh.ts (4 hunks)
- src/vim-loader/objectAttributes.ts (2 hunks)
- src/vim-loader/progressive/insertableSubmesh.ts (1 hunks)
- src/vim-loader/progressive/instancedSubmesh.ts (1 hunks)
- src/vim-webgl-viewer/camera/camera.ts (4 hunks)
- src/vim-webgl-viewer/gizmos/gizmos.ts (3 hunks)
- src/vim-webgl-viewer/gizmos/plan2D.ts (1 hunks)
- src/vim-webgl-viewer/gizmos/plans2D.ts (1 hunks)
- src/vim-webgl-viewer/raycaster.ts (2 hunks)
- src/vim-webgl-viewer/selection.ts (1 hunks)
🧰 Additional context used
🔇 Additional comments (23)
src/vim-loader/progressive/insertableSubmesh.ts (1)
12-12
: Approve the addition of themerged
property with suggestions.The addition of the
readonly merged = true
property looks good. However, I have a few suggestions to ensure its effectiveness and maintainability:
Consider adding a comment to document the purpose of this property. It would help other developers understand why it's always true and how it's used.
Verify that all usages of the previous
merged
getter have been updated to use this property instead. This change from a getter to a property might affect how the class is used elsewhere in the codebase.Given that this property is always
true
, consider if it's being used for type checking or interface implementation. If not, it might be more appropriate to use a type assertion or implement an interface explicitly, rather than having a constant property.To help verify the usage and impact of this change, you can run the following script:
This script will help identify where the
merged
property is being used and if there are any interfaces that might require it.✅ Verification successful
No usages of
merged
found in the codebase.The
readonly merged = true
property has been successfully added toInsertableSubmesh
. No references or dependencies on this property were detected in the current codebase, indicating that its addition does not impact existing functionality.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check for usages of InsertableSubmesh.merged in the codebase # Search for usages of InsertableSubmesh.merged echo "Usages of InsertableSubmesh.merged:" rg --type typescript "InsertableSubmesh.*\.merged" # Search for potential interface definitions that might require this property echo "\nPotential interfaces requiring 'merged' property:" rg --type typescript "interface.*\{[^}]*merged\s*:[^}]*\}"Length of output: 383
Script:
#!/bin/bash # Description: Check for usages of InsertableSubmesh.merged in TypeScript files # Search for usages of InsertableSubmesh.merged echo "Usages of InsertableSubmesh.merged:" rg -g "*.ts" -g "*.tsx" "InsertableSubmesh\..*\.merged" # Search for potential interface definitions that might require this property echo "\nPotential interfaces requiring 'merged' property:" rg -g "*.ts" -g "*.tsx" "interface\s+\w+\s*\{[^}]*merged\s*:\s*[^}]*\}"Length of output: 331
package.json (1)
56-56
: New dependency added: pdfjs-distThe addition of
pdfjs-dist
as a dependency is noted. This likely introduces PDF-related functionality to the project.Please ensure the following:
Verify that PDF functionality aligns with the project scope and requirements.
Check for any potential conflicts with existing dependencies.
Review known vulnerabilities for
pdfjs-dist@4.6.82
:Update project documentation to reflect this new capability.
Would you like assistance in updating the project documentation or creating a GitHub issue to track these tasks?
src/main.ts (2)
1-2
: LGTM: Import statement change for THREE.jsThe change to import the entire THREE.js module as a namespace is a good practice. It provides more flexibility and is consistent with common usage patterns of the THREE.js library.
Line range hint
1-43
: Overall changes look good, consider updating documentationThe changes to the
load
function enhance the viewer's capabilities by adding support for plans. The modifications integrate well with the existing code structure and are consistent with the PR objectives.To ensure maintainability and ease of use:
- Consider updating any relevant documentation to reflect these new capabilities.
- If there are unit tests for the
load
function, they should be updated to cover the new functionality.To ensure that documentation is up-to-date, let's check for any README files or documentation in the project:
This will help identify any documentation that might need to be updated to reflect the new plan functionality.
src/vim-webgl-viewer/gizmos/gizmos.ts (2)
10-10
: LGTM: New import statement for Plans2DThe import statement for
Plans2D
is correctly formatted and necessary for the new property being added to theGizmos
class.
57-58
: LGTM: New Plans2D propertyThe
plans
property is correctly declared as readonly and of typePlans2D
. Its public accessibility and placement within the class are consistent with the existing structure.src/vim-loader/objectAttributes.ts (3)
6-6
: LGTM: Import statement updated correctly.The addition of
SimpleMesh
to the import statement is consistent with its usage in theAttributeTarget
type definition. This change enhances the module's capability to work with different mesh types.
54-54
: LGTM: apply method updated for flexibility.The removal of the type assertion for
sub
asMergedSubmesh
allows for more generic handling of thesub
variable, which is consistent with the expandedAttributeTarget
type. This change improves the flexibility of theObjectAttribute
class in dealing with different types of mesh attributes.To ensure that this change doesn't introduce any compatibility issues, please verify that the
applyMerged
method can handle all possible types defined inAttributeTarget
. Run the following script to check for potential issues:#!/bin/bash # Description: Check compatibility of applyMerged method with AttributeTarget types # Test 1: Check the applyMerged method implementation echo "Implementation of applyMerged method:" ast-grep --lang typescript --pattern $'class ObjectAttribute { $$$ private applyMerged(sub: $_, number: number) { $$$ } $$$ }' # Test 2: Look for any type checks or assertions within applyMerged echo "Type checks or assertions in applyMerged:" rg --type typescript "applyMerged.*\{" -A 10 | rg "(instanceof|as |typeof)" # Test 3: Check for usage of properties specific to MergedSubmesh echo "Usage of MergedSubmesh-specific properties:" rg --type typescript "applyMerged.*\{" -A 20 | rg "(meshStart|meshEnd)"
8-8
: LGTM: AttributeTarget type updated correctly.The addition of
SimpleMesh
to theAttributeTarget
type definition expands the possible types that can be used for mesh attributes, which is consistent with the updated import statement.To ensure that this change doesn't introduce any unintended side effects, please verify the behavior of methods that use the
AttributeTarget
type, particularly theapply
method. Run the following script to check for any potential issues:src/vim-loader/colorAttributes.ts (2)
6-6
: LGTM: Import ofSimpleMesh
added correctly.The addition of
SimpleMesh
to the import statement is consistent with the changes described in the summary and follows the existing import style.
Line range hint
1-193
: Consider reviewing the entireColorAttribute
class for consistentSimpleMesh
handling.With the introduction of special handling for
SimpleMesh
instances in theresetMergedColor
method, it's important to ensure that other methods in theColorAttribute
class handleSimpleMesh
instances consistently. This may include methods likeapplyMergedColor
,applyInstancedColor
, and others.To assist with this review, you can run the following script to identify other methods in the
ColorAttribute
class that might need updates:Please review the output of this script and consider whether any other methods need to be updated to handle
SimpleMesh
instances consistently.src/vim-webgl-viewer/selection.ts (2)
10-10
: LGTM: Import statement for Plan2D is correct.The import statement for
Plan2D
is correctly added and is necessary for the subsequent type definition change.
Line range hint
1-248
: Summary: Plan2D integration looks good. Ensure comprehensive testing.The changes to include
Plan2D
as a selectable object type have been implemented correctly. TheSelection
class implementation appears to handle objects generically, which should accommodate the newPlan2D
type without further modifications.To ensure the integration is complete and correct:
- Verify that all
Selection
class methods work as expected withPlan2D
objects.- Add unit tests specifically for selecting, deselecting, and manipulating
Plan2D
objects.- Update any relevant documentation to reflect the new selectable object type.
Run the following script to identify potential areas that might need additional testing:
This script will help identify any type-specific handling in the
Selection
class methods, which might need to be updated or tested forPlan2D
objects.src/vim-loader/mesh.ts (4)
129-129
: Ensure correct handling of 'SealedSubmesh' in 'getSubmeshFromFace'The method
getSubmeshFromFace
now returnsSealedSubmesh
. Verify that any code that calls this method and expects aStandardSubmesh
is updated to handleSealedSubmesh
.
137-137
: Update code to handle 'SealedSubmesh' array from 'getSubmeshes'The
getSubmeshes
method now returns an array ofSealedSubmesh
instances. Ensure that all usages of this method are compatible withSealedSubmesh
and that any type assertions or expectations are updated accordingly.
167-168
: Review changes to 'MergedSubmesh' and 'Submesh' typesThe
MergedSubmesh
type now includesSealedSubmesh
,InsertableSubmesh
, andSimpleMesh
. TheSubmesh
type includesMergedSubmesh
andInstancedSubmesh
. Ensure that all code that uses these types is updated to handle the new type structure.Consider searching for usages of these types:
#!/bin/bash # Description: Find all usages of `MergedSubmesh` and `Submesh` to verify compatibility. # Test: Search for usages of `MergedSubmesh` and `Submesh` in TypeScript files. rg 'MergedSubmesh|Submesh' --type ts
118-118
: Verify compatibility of 'SealedSubmesh' with 'StandardSubmesh'The method
getSubMesh
now returnsSealedSubmesh
instead ofStandardSubmesh
. Ensure thatSealedSubmesh
provides all the methods and properties expected by code that usesgetSubMesh
.You can run the following script to find all usages of
getSubMesh
and check for any type incompatibilities:src/vim-webgl-viewer/raycaster.ts (4)
14-14
: ImportingPlan2D
The
Plan2D
class is now imported, enabling the raycasting functionality to includePlan2D
objects.
50-59
: Enhance raycasting to detectPlan2D
objectsThe
GetFirstHit
method now includes logic to detectPlan2D
instances in raycasting results. This broadens the interactable objects within the scene.
45-47
: Ensure consistent usage ofGetFirstHit
The method
GetFirstVimHit
has been replaced withGetFirstHit
. Verify that all references toGetFirstVimHit
have been updated throughout the codebase to prevent any broken references.Run the following script to check for any remaining references to
GetFirstVimHit
:#!/bin/bash # Description: Search for any occurrences of 'GetFirstVimHit' that may have been missed. rg 'GetFirstVimHit'
30-30
: Updateobject
property to includePlan2D
The
object
property inRaycastResult
now includesPlan2D
as a possible type. Ensure that all usages ofRaycastResult.object
handlePlan2D
instances correctly to prevent any runtime errors.Run the following script to find all references to
RaycastResult.object
and check for compatibility withPlan2D
:src/vim-webgl-viewer/camera/camera.ts (2)
160-160
: LGTM!The private field
_freeze
is appropriately initialized.
213-220
: Verify if events should be dispatched whenfreeze
is modifiedConsider whether the
freeze
property change should trigger any events, such as_onValueChanged
or_onMoved
, to notify other components of the state change.
const plan = await viewer.gizmos.plans.addPlan('https://vimdevelopment01storage.blob.core.windows.net/samples/floor_plan.png') | ||
const plan2 = await viewer.gizmos.plans.addPlan('https://vimdevelopment01storage.blob.core.windows.net/samples/floor_plan.pdf') | ||
plan.color = new THREE.Color(0x00ff00) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider parameterizing plan URLs and colors
The addition of plans to the viewer's gizmos enhances its capabilities. However, there are a few points to consider:
- The URLs for the plans are hardcoded. Consider parameterizing these for better maintainability.
- Only the first plan's color is set. Is this intentional? If not, consider setting colors for both plans or using a consistent approach.
Here's a suggestion to improve this section:
const planUrls = [
'https://vimdevelopment01storage.blob.core.windows.net/samples/floor_plan.png',
'https://vimdevelopment01storage.blob.core.windows.net/samples/floor_plan.pdf'
];
const planColors = [
new THREE.Color(0x00ff00),
new THREE.Color(0x0000ff) // Example second color
];
for (let i = 0; i < planUrls.length; i++) {
const plan = await viewer.gizmos.plans.addPlan(planUrls[i]);
plan.color = planColors[i];
}
This approach allows for easier management of multiple plans and their colors.
|
||
export type SelectableObject = Object3D | GizmoMarker | ||
export type SelectableObject = Object3D | GizmoMarker | Plan2D |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
Potential Issue: Selection class may not handle Plan2D objects
The SelectableObject
type has been updated to include Plan2D
, but there are no corresponding implementations in the Selection
class methods to handle Plan2D
objects. This omission could lead to unexpected behavior or runtime errors when Plan2D
objects are selected.
src/vim-webgl-viewer/selection.ts
- Line 12:
export type SelectableObject = Object3D | GizmoMarker | Plan2D
- Line 12:
🔗 Analysis chain
LGTM: SelectableObject type updated correctly. Verify class implementation.
The SelectableObject
type has been correctly updated to include Plan2D
. This change expands the selection capabilities as intended.
To ensure the Selection
class correctly handles the new Plan2D
type, please run the following verification script:
This script will help identify any potential issues or missing implementations related to the Plan2D
type in the Selection
class methods.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify that the Selection class methods handle Plan2D objects correctly.
# Test: Check if Plan2D is used in the Selection class methods
rg --type typescript -g 'src/vim-webgl-viewer/selection.ts' -e 'Plan2D' -C 5
# Test: Verify that no type errors are introduced by this change
ast-grep --lang typescript --pattern 'class Selection {
$$$
$_($$_: $$$Plan2D$$$) {
$$$
}
$$$
}'
Length of output: 484
Script:
#!/bin/bash
# Description: Verify that the Selection class methods handle Plan2D objects correctly.
# Test 1: Check if Plan2D is used in the Selection class methods
rg --type typescript -g 'src/vim-webgl-viewer/selection.ts' -e 'Plan2D' -C 5
# Test 2: Verify that no type errors are introduced by this change
ast-grep --lang typescript --pattern '
class Selection {
$$$
$_($$_: Plan2D) {
$$$
}
$$$
}
'
Length of output: 216
Script:
#!/bin/bash
# Description: Verify that the Selection class methods handle Plan2D objects correctly.
# Test 1: Check if Plan2D is used in the Selection class methods
rg -g 'src/vim-webgl-viewer/selection.ts' -e 'Plan2D' -C 5
# Test 2: Verify that no type errors are introduced by this change
ast-grep --lang typescript --pattern 'class Selection {
$$$
$_($$_: Plan2D) {
$$$
}
$$$
}'
Length of output: 1073
async addPlan (url: string): Promise<Plan2D> { | ||
let canvas: HTMLCanvasElement | ||
|
||
// Determine the file type based on the file extension | ||
const extension = url.split('.').pop()?.toLowerCase() | ||
if (extension === 'pdf') { | ||
canvas = await loadPdfAsImage(url) | ||
} else if (['png', 'jpg', 'jpeg', 'gif', 'bmp'].includes(extension!)) { | ||
canvas = await loadImageAsCanvas(url) | ||
} else { | ||
throw new Error('Unsupported file type') | ||
} | ||
|
||
const plan = new Plan2D(this._viewer, canvas) | ||
this._viewer.renderer.add(plan.mesh) | ||
return plan | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Validate input URLs to enhance security
Loading resources from external URLs without validation can introduce security vulnerabilities such as Cross-Site Scripting (XSS) or injection attacks. Consider validating the input URL to ensure it conforms to expected formats or domains, or sanitize it before usage.
Apply this diff to add basic URL validation:
async addPlan (url: string): Promise<Plan2D> {
+ if (!isValidUrl(url)) {
+ throw new Error('Invalid URL')
+ }
let canvas: HTMLCanvasElement
// Determine the file type based on the file extension
And define the isValidUrl
function:
function isValidUrl(url: string): boolean {
try {
new URL(url)
return true
} catch (e) {
return false
}
}
Further enhancements could include checking against a whitelist of allowed domains.
import * as PDF from 'pdfjs-dist' | ||
import { Plan2D } from './plan2D' | ||
|
||
PDF.GlobalWorkerOptions.workerSrc = 'node_modules/pdfjs-dist/build/pdf.worker.mjs' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make the PDF worker source path dynamic
Setting a hardcoded path for PDF.GlobalWorkerOptions.workerSrc
may lead to issues in different deployment environments where the path to pdf.worker.mjs
might vary. Consider using a dynamic import or configuring the worker source path based on the environment to ensure compatibility.
Apply this diff to use a dynamic import:
-PDF.GlobalWorkerOptions.workerSrc = 'node_modules/pdfjs-dist/build/pdf.worker.mjs'
+import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry'
+PDF.GlobalWorkerOptions.workerSrc = pdfjsWorker
Ensure that your build system supports loading worker files correctly.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
PDF.GlobalWorkerOptions.workerSrc = 'node_modules/pdfjs-dist/build/pdf.worker.mjs' | |
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry' | |
PDF.GlobalWorkerOptions.workerSrc = pdfjsWorker |
const canvas = document.createElement('canvas') | ||
canvas.width = image.width | ||
canvas.height = image.height | ||
const context = canvas.getContext('2d')! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handle potential null return from getContext('2d')
Similar to the previous comment, ensure that the canvas.getContext('2d')
call handles the possibility of returning null
.
Apply this diff:
-const context = canvas.getContext('2d')!
+const context = canvas.getContext('2d')
+if (!context) {
+ reject(new Error('2D rendering context is not available'))
+ return
+}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const context = canvas.getContext('2d')! | |
const context = canvas.getContext('2d') | |
if (!context) { | |
reject(new Error('2D rendering context is not available')) | |
return | |
} |
// Create a plane geometry (width and height based on canvas dimensions) | ||
this._geometry = new THREE.PlaneGeometry(100, 100) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Initialize plane geometry dimensions based on canvas size instead of scaling the mesh.
Currently, you're creating a PlaneGeometry
with fixed dimensions and then scaling the mesh to match the canvas size. This can be simplified by directly initializing the geometry with the canvas dimensions, improving code clarity and potentially performance.
Apply this diff to modify the geometry initialization and remove the scaling:
// Create a plane geometry with dimensions based on canvas size
- this._geometry = new THREE.PlaneGeometry(100, 100)
+ const width = canvas.width * 0.001
+ const height = canvas.height * 0.001
+ this._geometry = new THREE.PlaneGeometry(width, height)
- frameMesh.scale.set(canvas.width, canvas.height, 1).multiplyScalar(0.001)
Also applies to: 50-50
window.addEventListener('keydown', onKey) | ||
this._subs.push(() => window.removeEventListener('keydown', onKey)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid attaching global 'keydown' event listener to the window object and prevent default browser actions.
Attaching a 'keydown' event listener to the global window
object can lead to unintended side effects and potential conflicts with other components. Additionally, handling keys like 't', 'r', and 's' without preventing default browser behavior might interfere with the application's functionality.
Solution: Attach the event listener to the viewer's canvas and prevent default actions.
Apply this diff to attach the event listener to the canvas and prevent default behavior:
const onKey = (event: KeyboardEvent): void => {
if (!this.selected) return
+ event.preventDefault()
switch (event.key) {
case 't': // 't' for translate
gizmo.setMode('translate')
break
case 'r': // 'r' for rotate
gizmo.setMode('rotate')
break
case 's': // 's' for scale
gizmo.setMode('scale')
break
}
}
- window.addEventListener('keydown', onKey)
- this._subs.push(() => window.removeEventListener('keydown', onKey))
+ this._viewer.viewport.canvas.tabIndex = 0 // Ensure the canvas can receive focus
+ this._viewer.viewport.canvas.addEventListener('keydown', onKey)
+ this._subs.push(() => this._viewer.viewport.canvas.removeEventListener('keydown', onKey))
Additional Note: Setting tabIndex = 0
on the canvas element allows it to receive keyboard events when focused. Ensure that the canvas is focused appropriately within your application.
Also applies to: 103-115
get size (): THREE.Vector2 { | ||
return new THREE.Vector2(this.mesh.scale.x, this.mesh.scale.y) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Optimize 'size' getter and setter to reuse a Vector2 instance and improve performance.
Creating a new THREE.Vector2
instance every time the size
getter is called can lead to unnecessary memory allocations. Reusing a single instance improves performance, especially if size
is accessed frequently.
Introduce a private _size
property and update it accordingly:
+ private readonly _size: THREE.Vector2 = new THREE.Vector2()
get size (): THREE.Vector2 {
- return new THREE.Vector2(this.mesh.scale.x, this.mesh.scale.y)
+ return this._size.set(this.mesh.scale.x, this.mesh.scale.y)
}
set size (value: THREE.Vector2) {
this.mesh.scale.set(value.x, value.y, 1)
this.mesh.geometry.computeBoundingBox()
this._viewer.renderer.needsUpdate = true
+ this._size.copy(value)
}
Also applies to: 220-224
return this._force | ||
? new THREE.Vector3(1, 1, 1) | ||
: this._freeze | ||
? new THREE.Vector3(0, 0, 0) | ||
: this._allowedMovement |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Improve readability by replacing nested ternary operators with if-else statements
Nested ternary operators can be hard to read and maintain. Consider refactoring the getter to use if-else statements for better clarity.
Apply this diff to improve readability:
get allowedMovement () {
- return this._force
- ? new THREE.Vector3(1, 1, 1)
- : this._freeze
- ? new THREE.Vector3(0, 0, 0)
- : this._allowedMovement
+ if (this._force) {
+ return new THREE.Vector3(1, 1, 1)
+ } else if (this._freeze) {
+ return new THREE.Vector3(0, 0, 0)
+ } else {
+ return this._allowedMovement
+ }
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
return this._force | |
? new THREE.Vector3(1, 1, 1) | |
: this._freeze | |
? new THREE.Vector3(0, 0, 0) | |
: this._allowedMovement | |
get allowedMovement () { | |
if (this._force) { | |
return new THREE.Vector3(1, 1, 1) | |
} else if (this._freeze) { | |
return new THREE.Vector3(0, 0, 0) | |
} else { | |
return this._allowedMovement | |
} | |
} |
return this._force | ||
? new THREE.Vector2(1, 1) | ||
: this._freeze | ||
? new THREE.Vector2(0, 0) | ||
: this._allowedRotation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Improve readability by replacing nested ternary operators with if-else statements
Nested ternary operators can be hard to read and maintain. Consider refactoring the getter to use if-else statements for better clarity.
Apply this diff to improve readability:
get allowedRotation () {
- return this._force
- ? new THREE.Vector2(1, 1)
- : this._freeze
- ? new THREE.Vector2(0, 0)
- : this._allowedRotation
+ if (this._force) {
+ return new THREE.Vector2(1, 1)
+ } else if (this._freeze) {
+ return new THREE.Vector2(0, 0)
+ } else {
+ return this._allowedRotation
+ }
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
return this._force | |
? new THREE.Vector2(1, 1) | |
: this._freeze | |
? new THREE.Vector2(0, 0) | |
: this._allowedRotation | |
get allowedRotation () { | |
if (this._force) { | |
return new THREE.Vector2(1, 1) | |
} else if (this._freeze) { | |
return new THREE.Vector2(0, 0) | |
} else { | |
return this._allowedRotation | |
} | |
} |
Summary by CodeRabbit
Release Notes
New Features
Plan2D
andPlans2D
classes for enhanced 2D visualization within the 3D viewer.freeze
functionality to the camera, allowing for temporary halting of movement.Plan2D
objects.Plan2D
objects.Improvements
Bug Fixes
These updates enhance user interaction and visualization capabilities in the viewer.