こんにちは。troika-worker.utils.esm.jsからこのメッセージとともに大量の警告が表示されています。
すべてが正常に機能しているようですが
何か案が?
うーん、その警告は、1000を超えるオープンワーカーリクエストがあるまでトリガーされません。 非常に多くのテキストインスタンスがありますか?
私はそうしますが、1000を超えない(少なくとも意図的にではない)
数百のように
これが私がレンダリングしているものです
しかし、実際に必要な数よりも多くのインスタンスを作成し、1000カウントを超えるとエラーが発生し始めるという、私の側にバグがあるのではないかとおっしゃっていますか?
コンテンツのないインスタンスを.visible = falseに設定しています
しかし、それでもインスタンスが存在することを意味すると思います
未使用のインスタンスを完全に削除するために.visiblepropを使用する代わりに、お勧めしますか?
ああ、それはそれを説明することができます。 .sync()の呼び出しは、 visible:falseであっても、バックグラウンドでワーカーに発行され、積み重なっていきます。
私は個人的にラベルをオンデマンドで作成/破棄することを選択するか、少なくとも非表示のラベルに対する.sync()呼び出しを防ぐことを選択すると思います。 これらのワーカーリクエストはすべて同じワーカーを使用するため、非表示のラベルの処理でビジー状態の場合は、表示されているラベルの処理が遅れる可能性があります。
ただし、正確なLabelViewコードを見たことがないという仮定を立てています。 私の側にバグがある可能性はまだあるので、あなたが見つけたものをLMKします。
.visible === trueの場合にのみ.sync()を呼び出そうとしました
しかし、それでも警告が表示されます
代わりに、表示されているオブジェクトのインスタンスのみを作成し、未使用のオブジェクトを破棄すると、警告は消えます
うーん、 Text
自体はonBeforeRenderでsync()を呼び出すだけで、visible = falseの場合はトリガーしないでください。
LabelViewラッパーコードは、私が覗くことができる場所ならどこでも利用できますか?
クローズドソースプロジェクトの一部です
しかし、ここに関連するクラスがあります。これで十分かもしれません。
import {Mesh, MeshBasicMaterial} from "three";
import R from "../../../../../../../../../../resources/Namespace";
import BaseView, {ViewType} from "./BaseView";
import {Text} from "troika-three-text";
import {GeometryInstances} from "../instances/GeometryInstances";
import {MaterialInstances} from "../instances/MaterialInstances";
export enum TextAlign {
left = "left",
right = "right",
center = "center",
justify = "justify",
}
export enum HorizontalAlign {
left = "left",
right = "right",
center = "center",
}
export enum VerticalAlign {
top = "top",
topBaseline = "top-baseline",
middle = "middle",
bottomBaseline = "bottom-baseline",
bottom = "bottom",
}
export interface ILabelData {
content: string;
fontFace?: string;
fontSize?: number;
alignment?: TextAlign;
horizontalAlign?: HorizontalAlign;
verticalAlign?: VerticalAlign;
color?: string;
opacity?: number;
backgroundColor?: string;
highlightable: boolean;
}
export default class LabelView extends BaseView {
get viewObject() {
return this._viewObject as any;
}
get content() {
return this.textMesh.text;
}
set content(content: string) {
if (content !== this.textMesh.text) {
this.textMesh.text = content;
this.textMesh.visible = !!content;
this.syncIfVisible();
}
}
private syncIfVisible() {
// Better for perf: https://github.com/protectwise/troika/issues/112
if (this.textMesh?.text && this.textMesh?.visible && this._isVisible) {
this.textMesh.sync();
}
}
set textAlign(alignment: TextAlign) {
this.textMesh.textAlign = alignment;
this.syncIfVisible();
}
set horizontalAlign(alignment: HorizontalAlign) {
this.textMesh.anchorX = alignment;
this.syncIfVisible();
}
set verticalAlign(alignment: VerticalAlign) {
this.textMesh.anchorY = alignment;
this.syncIfVisible();
}
private backgroundMesh: Mesh | undefined;
private readonly textMesh: any;
private readonly foregroundColor: string;
private highlightable: boolean;
constructor(labelData: ILabelData) {
super(ViewType.Label);
this.foregroundColor = labelData.color || R.colors.elements.labels.foreground;
this.highlightable = labelData.highlightable;
if (labelData.backgroundColor) {
this.textMesh = this.createTextMesh(
labelData.content,
labelData.fontFace,
labelData.fontSize,
labelData.alignment,
labelData.horizontalAlign,
labelData.verticalAlign,
this.foregroundColor,
labelData.opacity,
1);
this.textMesh.addEventListener("synccomplete", () => {
if (this.backgroundMesh) {
this._viewObject.remove(this.backgroundMesh);
}
if (this.textMesh.text) {
const bounds = this.textMesh.textRenderInfo.blockBounds;
this.backgroundMesh =
this.createBackgroundBox(bounds[0], bounds[1], bounds[2], bounds[3], 0);
this._viewObject.add(this.backgroundMesh);
}
});
} else {
this.textMesh = this.createTextMesh(
labelData.content,
labelData.fontFace,
labelData.fontSize,
labelData.alignment,
labelData.horizontalAlign,
labelData.verticalAlign,
this.foregroundColor,
labelData.opacity,
0);
}
this.syncIfVisible();
this._viewObject.add(this.textMesh);
}
public onFrameRendered(elapsedTime: number) {
if (this.highlightable) {
this.setLabelHighlightState();
}
}
private setLabelHighlightState() {
const labelMaterial = this.textMesh.material as MeshBasicMaterial;
if (this._isHighlighted) {
labelMaterial.color.set(R.colors.elements.labels.highlighted);
} else {
labelMaterial.color.set(this.foregroundColor);
}
}
private createTextMesh(content: string,
fontFace = R.layout.labels.font_face.regular,
fontSize = R.layout.labels.font_size,
textAlign = TextAlign.center,
horizontalAlign = HorizontalAlign.center,
verticalAlign = VerticalAlign.middle,
color: string,
opacity = 1,
zLevel: number) {
const labelMesh = new Text();
labelMesh.font = fontFace;
labelMesh.text = content || "";
labelMesh.fontSize = fontSize;
labelMesh.position.z = zLevel;
labelMesh.color = color;
labelMesh.textAlign = textAlign;
labelMesh.anchorX = horizontalAlign;
labelMesh.anchorY = verticalAlign;
labelMesh.material.opacity = opacity;
labelMesh.name = "LabelView";
return labelMesh;
}
private createBackgroundBox(startX: number, startY: number, endX: number, endY: number, zLevel: number) {
const paddingLeft = 1;
const paddingRight = 2;
const paddingTop = 1;
const paddingBottom = 0;
const width = Math.abs(startX) + Math.abs(endX) + paddingLeft + paddingRight;
const height = Math.abs(startY) + Math.abs(endY) + (paddingTop + paddingBottom);
const geometry = GeometryInstances.getInstance().getPlaneGeometryInstance(width, height);
const material = MaterialInstances.getInstance().backgroundColorMaterial;
const mesh = new Mesh(geometry, material);
const posX = ((startX + endX) / 2) + (paddingLeft / 4);
const posY = ((startY + endY) / 2) - (paddingBottom);
// The z level of element in accordance with standards defined in resources
mesh.position.set(posX, posY, zLevel);
mesh.name = "LabelBackgroundBox";
return mesh;
}
}
うーん、私の予感は.visibleがfalseに設定される前にsyncIfVisible()が呼び出されることですが、ビューシステムがどのように機能するかを知らずに確実に言うのは難しいです。
私が気付いている他の何かは、個々のプロパティが変更されるたびにsyncIfVisible呼び出しを発行していることです(content、textAlign、horizontalAlignなど)。これにより、必要以上にワーカーに呼び出しが発行されます。 ビューシステムに、すべての個別のプロパティが設定された後に単一の同期呼び出しを発行できるライフサイクルがある場合、それははるかに優れています。
あなたが説明したことから、この警告は期待どおりに動作していると思います。 パフォーマンスの問題を正しく強調しました。 この号を締めくくります。 信じ方が違う場合は、お気軽に再開してください。 ありがとう!
これに戻るだけです
したがって、シーンには1000を超えるテキストインスタンスが簡単に含まれていることがわかります。 しかし、すべてが同時に見えるわけではありません
それらの多くは、特定のオブジェクトの上にマウスを置くと表示されます
だから私は前進するための最良の方法はここにあるのだろうかと思っています:
個人的には最初の選択肢を選びます。 私は間違っている可能性がありますが、これらすべての非表示のラベルオブジェクトをシーングラフに表示することにメリットはないと思います。
とった
オブジェクトのマウスホバーですばやく表示できるようにする必要があります
使用後にそれらを破棄してホバーで新しいものを作成することをお勧めしますか、それとも代わりにthreeJsシーンからそれらを削除することをお勧めしますか?
正直なところ、どちらにしても目立った違いはないと思います。 問題に気付いた場合にのみ、管理と最適化が最も簡単なものから始めます。
個人的には、作成/破棄のアプローチをたくさん行ってきましたが、それは私にとって常に非常にきびきびとしています。