Skip to content

Commit

Permalink
Merge branch '153-custom-arrows' into 'main'
Browse files Browse the repository at this point in the history
Use custom mesh for communication arrows and add config options

Closes #153

See merge request ExplorViz/code/frontend!249
  • Loading branch information
Malte-Hansen committed Feb 13, 2025
2 parents 789d81c + fe85ce0 commit de67ebe
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ export default class Settings extends Component<Args> {
break;
case 'commThickness':
case 'commArrowSize':
case 'commArrowOffset':
case 'curvyCommHeight':
if (this.args.redrawCommunication && this.args.updateHighlighting) {
this.args.redrawCommunication();
Expand Down
18 changes: 7 additions & 11 deletions app/services/link-renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,23 +182,19 @@ export default class LinkRenderer extends Service.extend({}) {
viewCenterPoint: THREE.Vector3
) {
pipe.children.forEach((child) => {
if (child instanceof CommunicationArrowMesh) child.dispose();
pipe.remove(child);
if (child instanceof CommunicationArrowMesh) {
pipe.remove(child);
child.disposeRecursively();
}
});

const arrowOffset = 1;
const arrowOffset = this.appSettings.commArrowOffset.value;
const arrowHeight = curveHeight / 2 + arrowOffset;
const arrowThickness = this.appSettings.commArrowSize.value;
const arrowColorHex =
this.userSettings.colors.communicationArrowColor.getHex();
const arrowColor = this.userSettings.colors.communicationArrowColor;

if (arrowThickness > 0.0) {
pipe.addArrows(
viewCenterPoint,
arrowThickness,
arrowHeight,
arrowColorHex
);
pipe.addArrows(viewCenterPoint, arrowThickness, arrowHeight, arrowColor);
}

if (pipe.material.opacity !== 1) {
Expand Down
13 changes: 4 additions & 9 deletions app/utils/application-rendering/communication-rendering.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,14 @@ export default class CommunicationRendering {
curveHeight: number,
viewCenterPoint: Vector3
) {
const arrowOffset = 0.8;
const arrowOffset =
this.userSettings.visualizationSettings.commArrowOffset.value;
const arrowHeight = curveHeight / 2 + arrowOffset;
const arrowThickness = this.appSettings.commArrowSize.value;
const arrowColorHex =
this.userSettings.colors.communicationArrowColor.getHex();
const arrowColor = this.userSettings.colors.communicationArrowColor;

if (arrowThickness > 0.0) {
pipe.addArrows(
viewCenterPoint,
arrowThickness,
arrowHeight,
arrowColorHex
);
pipe.addArrows(viewCenterPoint, arrowThickness, arrowHeight, arrowColor);
}
}

Expand Down
4 changes: 0 additions & 4 deletions app/utils/application-rendering/entity-manipulation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import MessageSender from 'explorviz-frontend/services/collaboration/message-sen
import FoundationMesh from 'explorviz-frontend/view-objects/3d/application/foundation-mesh';
import gsap from 'gsap';
import BaseMesh from 'explorviz-frontend/view-objects/3d/base-mesh';
import CommunicationArrowMesh from 'explorviz-frontend/view-objects/3d/application/communication-arrow-mesh';
import { ExplorVizColors } from 'explorviz-frontend/services/user-settings';
import {
getStoredNumberSetting,
Expand Down Expand Up @@ -471,9 +470,6 @@ export function updateColors(
scene.traverse((object3D) => {
if (object3D instanceof BaseMesh) {
object3D.updateColor();
// Special case because communication arrow is no base mesh
} else if (object3D instanceof CommunicationArrowMesh) {
object3D.updateColor(applicationColors.communicationArrowColor);
}
});
scene.background = applicationColors.backgroundColor;
Expand Down
2 changes: 1 addition & 1 deletion app/utils/raycaster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ export function defaultRaycastFilter(
return !(
intersection.object instanceof LabelMesh ||
intersection.object instanceof LogoMesh ||
intersection.object.parent instanceof CommunicationArrowMesh ||
intersection.object instanceof PingMesh ||
intersection.object instanceof CrosshairMesh ||
intersection.object instanceof CommunicationArrowMesh ||
intersection.object.type === 'AxesHelper' ||
isChildOfText(intersection)
);
Expand Down
15 changes: 12 additions & 3 deletions app/utils/settings/default-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,19 +234,28 @@ export const defaultVizSettings: VisualizationSettings = {
commArrowSize: {
level: SettingLevel.DEFAULT,
value: 2.0,
range: { min: 0.0, max: 5.0, step: 0.25 },
range: { min: 0.0, max: 10.0, step: 0.25 },
group: 'Communication',
displayName: 'Arrow Size in Application Visualization',
displayName: 'Arrow Size',
description:
'Arrow Size for selected communications in application visualization',
isRangeSetting: true,
},
commArrowOffset: {
level: SettingLevel.EXTENDED,
value: 4.0,
range: { min: -20.0, max: 20.0, step: 0.25 },
group: 'Communication',
displayName: 'Arrow Offset',
description: 'Distance between arrow and communication line',
isRangeSetting: true,
},
curvyCommHeight: {
level: SettingLevel.DEFAULT,
value: 1.0,
range: { min: 0.0, max: 5.0, step: 0.1 },
group: 'Communication',
displayName: 'Curviness Factor of the Communication Lines',
displayName: 'Communication Curviness',
description:
'If greater 0.0, communication lines are rendered arc-shaped (Straight lines: 0.0)',
isRangeSetting: true,
Expand Down
1 change: 1 addition & 0 deletions app/utils/settings/settings-schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export type ControlSettings = {
export type CommunicationSettingId =
| 'commThickness'
| 'commArrowSize'
| 'commArrowOffset'
| 'curvyCommHeight';

export type CommunicationSettings = Record<
Expand Down
10 changes: 5 additions & 5 deletions app/view-objects/3d/application/clazz-communication-mesh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,9 @@ export default class ClazzCommunicationMesh extends BaseMesh {
*/
addArrows(
applicationCenter = new THREE.Vector3(),
width = 1,
yOffset = 1,
color = 0x000000
width: number,
yOffset: number,
color: THREE.Color
) {
const { layout } = this;
// Scale arrow with communication line thickness
Expand Down Expand Up @@ -307,7 +307,7 @@ export default class ClazzCommunicationMesh extends BaseMesh {
end: THREE.Vector3,
width: number,
yOffset: number,
color: number
color: THREE.Color
) {
const dir = new THREE.Vector3().subVectors(end, start);
const len = dir.length();
Expand Down Expand Up @@ -354,7 +354,7 @@ export default class ClazzCommunicationMesh extends BaseMesh {
end: THREE.Vector3,
width: number,
yOffset: number,
color: number
color: THREE.Color
) {
const dir = new THREE.Vector3().subVectors(end, start);
const len = dir.length();
Expand Down
101 changes: 48 additions & 53 deletions app/view-objects/3d/application/communication-arrow-mesh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import ClassCommunication from 'explorviz-frontend/utils/landscape-schemes/dynam
import ComponentCommunication from 'explorviz-frontend/utils/landscape-schemes/dynamic/component-communication';
import * as THREE from 'three';
import { SemanticZoomableObjectBaseMixin } from './utils/semantic-zoom-manager';
import BaseMesh from 'explorviz-frontend/view-objects/3d/base-mesh';

class CommunicationArrowMeshPrivate extends THREE.ArrowHelper {
class CommunicationArrowMeshPrivate extends BaseMesh {
dataModel: ClassCommunication | ComponentCommunication;

_axis = new THREE.Vector3();
isHovered = false;

HOVER_Y_TRANSLATION = 2;
Expand All @@ -17,42 +19,51 @@ class CommunicationArrowMeshPrivate extends THREE.ArrowHelper {
dir: THREE.Vector3,
origin: THREE.Vector3,
length: number,
color: number,
color: THREE.Color,
headLength: number,
headWidth: number
) {
super(dir, origin, length, color, headLength, headWidth);
super(color);
this.dataModel = dataModel;

this.material = new THREE.MeshBasicMaterial({
color: color,
toneMapped: false,
});
this.geometry = new THREE.CylinderGeometry(0, 0.5, 1, 5, 1);
this.geometry.translate(0, -0.5, 0);

this.position.copy(origin);

this.matrixAutoUpdate = true;

this.setDirection(dir);
this.setLength(length, headLength, headWidth);
}

/**
* Deletes this arrow from its parent and dispose the arrow's geomeries and materials
*/
delete() {
if (this.parent) {
this.parent.remove(this);
}
const { line } = this;
line.geometry.dispose();
setDirection(dir: THREE.Vector3) {
// dir is assumed to be normalized

if (line.material instanceof THREE.Material) {
line.material.dispose();
}
if (dir.y > 0.99999) {
this.quaternion.set(0, 0, 0, 1);
} else if (dir.y < -0.99999) {
this.quaternion.set(1, 0, 0, 0);
} else {
this._axis.set(dir.z, 0, -dir.x).normalize();

const radians = Math.acos(dir.y);

const { cone } = this;
cone.geometry.dispose();
if (cone.material instanceof THREE.Material) {
cone.material.dispose();
this.quaternion.setFromAxisAngle(this._axis, radians);
}
}

updateColor(color: THREE.Color) {
if (this.line.material instanceof THREE.LineBasicMaterial) {
this.line.material.color = color;
}
if (this.cone.material instanceof THREE.MeshBasicMaterial) {
this.cone.material.color = color;
}
setLength(
length: number,
headLength = length * 0.2,
headWidth = headLength * 0.2
) {
this.scale.set(headWidth, headLength, headWidth);
this.updateMatrix();
}

/**
Expand All @@ -63,40 +74,24 @@ class CommunicationArrowMeshPrivate extends THREE.ArrowHelper {
changeOpacity(opacity: number) {
const isTransparent = opacity < 1;

if (this.line.material instanceof THREE.Material) {
this.line.material.opacity = opacity;
this.line.material.transparent = isTransparent;
this.line.material.needsUpdate = true;
}

if (this.cone.material instanceof THREE.Material) {
this.cone.material.opacity = opacity;
this.cone.material.transparent = isTransparent;
this.cone.material.needsUpdate = true;
if (this.material instanceof THREE.Material) {
this.material.opacity = opacity;
this.material.transparent = isTransparent;
this.material.needsUpdate = true;
}
}

hide() {
if (this.line.material instanceof THREE.Material) {
this.line.material.visible = false;
this.line.material.needsUpdate = true;
}

if (this.cone.material instanceof THREE.Material) {
this.cone.material.visible = false;
this.cone.material.needsUpdate = true;
if (this.material instanceof THREE.Material) {
this.material.visible = false;
this.material.needsUpdate = true;
}
}

show() {
if (this.line.material instanceof THREE.Material) {
this.line.material.visible = true;
this.line.material.needsUpdate = true;
}

if (this.cone.material instanceof THREE.Material) {
this.cone.material.visible = true;
this.cone.material.needsUpdate = true;
if (this.material instanceof THREE.Material) {
this.material.visible = true;
this.material.needsUpdate = true;
}
}

Expand Down Expand Up @@ -153,7 +148,7 @@ export default class CommunicationArrowMesh extends SemanticZoomableObjectBaseMi
dir: THREE.Vector3,
origin: THREE.Vector3,
length: number,
color: number,
color: THREE.Color,
headLength: number,
headWidth: number
) {
Expand Down

0 comments on commit de67ebe

Please sign in to comment.