@lv-x-software-house/x_view 1.2.5-dev.43 → 1.2.5-dev.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +219 -89
- package/dist/index.mjs +219 -89
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1334,6 +1334,15 @@ var createNodeMesh = (nodeData, position, glowTexture) => {
|
|
|
1334
1334
|
label.name = "label";
|
|
1335
1335
|
mesh.userData.labelObject = label;
|
|
1336
1336
|
mesh.userData.labelOffset = new THREE.Vector3(0, 3.8, 0);
|
|
1337
|
+
if (nodeData.is_quest && nodeData.Date) {
|
|
1338
|
+
const timeInfo = parseDateProp(nodeData.Date);
|
|
1339
|
+
if (!timeInfo.isUndated && timeInfo.label) {
|
|
1340
|
+
const dateSprite = createTextSprite(timeInfo.label, 36);
|
|
1341
|
+
dateSprite.name = "questDateLabel";
|
|
1342
|
+
dateSprite.position.set(0, -5.5, 0);
|
|
1343
|
+
mesh.add(dateSprite);
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1337
1346
|
return mesh;
|
|
1338
1347
|
};
|
|
1339
1348
|
var updateExistingNodeVisuals = (state, updatedNode) => {
|
|
@@ -3321,9 +3330,14 @@ var userActionHandlers = {
|
|
|
3321
3330
|
};
|
|
3322
3331
|
specificParentData.nodes.push(nextQuestNode);
|
|
3323
3332
|
if (stateRef.current.nodeObjects[String(nodeToSave.id)]) {
|
|
3324
|
-
const
|
|
3325
|
-
|
|
3326
|
-
|
|
3333
|
+
const oldMeshPosition = stateRef.current.nodeObjects[String(nodeToSave.id)].position.clone();
|
|
3334
|
+
setTimeout(() => {
|
|
3335
|
+
if (stateRef.current && stateRef.current.graphGroup) {
|
|
3336
|
+
const pos = oldMeshPosition.clone();
|
|
3337
|
+
pos.x += 12;
|
|
3338
|
+
addStandaloneNodeToScene(stateRef.current, nextQuestNode, pos);
|
|
3339
|
+
}
|
|
3340
|
+
}, 2e3);
|
|
3327
3341
|
}
|
|
3328
3342
|
}
|
|
3329
3343
|
}
|
|
@@ -4266,6 +4280,78 @@ function calculateNextRecurrenceDate(config) {
|
|
|
4266
4280
|
confirmed: true
|
|
4267
4281
|
};
|
|
4268
4282
|
}
|
|
4283
|
+
var parseDate = (str) => {
|
|
4284
|
+
if (!str) return null;
|
|
4285
|
+
const parts = str.split("/");
|
|
4286
|
+
if (parts.length === 3) {
|
|
4287
|
+
const day = parseInt(parts[0], 10);
|
|
4288
|
+
const month = parseInt(parts[1], 10) - 1;
|
|
4289
|
+
const year = parseInt(parts[2], 10);
|
|
4290
|
+
if (!isNaN(day) && !isNaN(month) && !isNaN(year)) {
|
|
4291
|
+
return new Date(year, month, day);
|
|
4292
|
+
}
|
|
4293
|
+
}
|
|
4294
|
+
return null;
|
|
4295
|
+
};
|
|
4296
|
+
var parseDateProp = (dateProp) => {
|
|
4297
|
+
let info = { isUndated: true, label: "", type: "point" };
|
|
4298
|
+
if (!dateProp) return info;
|
|
4299
|
+
if (dateProp.type === "Data") {
|
|
4300
|
+
const d = parseDate(dateProp.value);
|
|
4301
|
+
if (d) {
|
|
4302
|
+
info = { startDate: d, endDate: d, label: dateProp.value, type: "point", isUndated: false };
|
|
4303
|
+
}
|
|
4304
|
+
} else if (dateProp.type === "Date Interval" || dateProp.type === "Date Range" || dateProp.type === "interval") {
|
|
4305
|
+
const sd = parseDate(dateProp.start || dateProp.value);
|
|
4306
|
+
const ed = parseDate(dateProp.end);
|
|
4307
|
+
if (sd) {
|
|
4308
|
+
info = {
|
|
4309
|
+
startDate: sd,
|
|
4310
|
+
endDate: ed || sd,
|
|
4311
|
+
label: `${dateProp.start || dateProp.value}${ed ? " - " + dateProp.end : ""}`,
|
|
4312
|
+
type: ed ? "interval" : "point",
|
|
4313
|
+
isUndated: false
|
|
4314
|
+
};
|
|
4315
|
+
}
|
|
4316
|
+
} else if (dateProp.date) {
|
|
4317
|
+
const d = parseDate(dateProp.date);
|
|
4318
|
+
if (d)
|
|
4319
|
+
info = {
|
|
4320
|
+
startDate: d,
|
|
4321
|
+
endDate: d,
|
|
4322
|
+
label: dateProp.date,
|
|
4323
|
+
type: "point",
|
|
4324
|
+
isUndated: false
|
|
4325
|
+
};
|
|
4326
|
+
} else if (dateProp.year) {
|
|
4327
|
+
const y = parseInt(dateProp.year, 10);
|
|
4328
|
+
if (!isNaN(y)) {
|
|
4329
|
+
const d = new Date(y, 0, 1);
|
|
4330
|
+
info = {
|
|
4331
|
+
startDate: d,
|
|
4332
|
+
endDate: d,
|
|
4333
|
+
label: String(y),
|
|
4334
|
+
type: "point",
|
|
4335
|
+
isUndated: false
|
|
4336
|
+
};
|
|
4337
|
+
}
|
|
4338
|
+
} else if (dateProp.date_interval && dateProp.date_interval.start) {
|
|
4339
|
+
const sY = parseInt(dateProp.date_interval.start, 10);
|
|
4340
|
+
const eY = parseInt(dateProp.date_interval.end, 10) || sY;
|
|
4341
|
+
if (!isNaN(sY)) {
|
|
4342
|
+
const sd = new Date(sY, 0, 1);
|
|
4343
|
+
const ed = new Date(eY, 11, 31);
|
|
4344
|
+
info = {
|
|
4345
|
+
startDate: sd,
|
|
4346
|
+
endDate: ed,
|
|
4347
|
+
label: `${sY} - ${eY}`,
|
|
4348
|
+
type: "interval",
|
|
4349
|
+
isUndated: false
|
|
4350
|
+
};
|
|
4351
|
+
}
|
|
4352
|
+
}
|
|
4353
|
+
return info;
|
|
4354
|
+
};
|
|
4269
4355
|
|
|
4270
4356
|
// src/components/CustomPropertyDisplay.jsx
|
|
4271
4357
|
var import_react4 = __toESM(require("react"));
|
|
@@ -9472,7 +9558,7 @@ function InSceneQuestForm({
|
|
|
9472
9558
|
textureImageUrl: null,
|
|
9473
9559
|
reviewStack,
|
|
9474
9560
|
timeline: initialTimeline,
|
|
9475
|
-
Date: questDate,
|
|
9561
|
+
Date: questDate ? { ...questDate, confirmed: true } : null,
|
|
9476
9562
|
recurrence_config: recurrenceConfig,
|
|
9477
9563
|
...additionalData
|
|
9478
9564
|
});
|
|
@@ -10936,7 +11022,7 @@ ${noteText}` : noteText : entry.notes,
|
|
|
10936
11022
|
description_sections: processedSections,
|
|
10937
11023
|
intensity,
|
|
10938
11024
|
recurrence_config: currentRecurrenceConfig,
|
|
10939
|
-
Date: questDate,
|
|
11025
|
+
Date: questDate ? { ...questDate, confirmed: true } : null,
|
|
10940
11026
|
useImageAsTexture: false,
|
|
10941
11027
|
textureImageUrl: null,
|
|
10942
11028
|
is_quest: true,
|
|
@@ -13499,7 +13585,7 @@ function XViewScene({
|
|
|
13499
13585
|
}
|
|
13500
13586
|
}
|
|
13501
13587
|
Object.values(nodeObjects).forEach((mesh) => {
|
|
13502
|
-
const oldLabel = mesh.getObjectByName("timelineLabel")
|
|
13588
|
+
const oldLabel = mesh.getObjectByName("timelineLabel");
|
|
13503
13589
|
if (oldLabel) {
|
|
13504
13590
|
mesh.remove(oldLabel);
|
|
13505
13591
|
if (oldLabel.material.map) oldLabel.material.map.dispose();
|
|
@@ -13510,7 +13596,7 @@ function XViewScene({
|
|
|
13510
13596
|
});
|
|
13511
13597
|
const timelineNodes = [];
|
|
13512
13598
|
const allTimePoints = /* @__PURE__ */ new Set();
|
|
13513
|
-
const
|
|
13599
|
+
const parseDate2 = (str) => {
|
|
13514
13600
|
const parts = str.split("/");
|
|
13515
13601
|
if (parts.length === 3) {
|
|
13516
13602
|
const day = parseInt(parts[0], 10);
|
|
@@ -13527,7 +13613,7 @@ function XViewScene({
|
|
|
13527
13613
|
let nodeInfo = { mesh, type: "point", label: "", isUndated: true };
|
|
13528
13614
|
if (dateProp) {
|
|
13529
13615
|
if (dateProp.date) {
|
|
13530
|
-
const date =
|
|
13616
|
+
const date = parseDate2(dateProp.date);
|
|
13531
13617
|
if (date) {
|
|
13532
13618
|
nodeInfo.startDate = date;
|
|
13533
13619
|
nodeInfo.endDate = date;
|
|
@@ -13673,7 +13759,7 @@ function XViewScene({
|
|
|
13673
13759
|
});
|
|
13674
13760
|
const timelineNodes = [];
|
|
13675
13761
|
const allTimePoints = /* @__PURE__ */ new Set();
|
|
13676
|
-
const
|
|
13762
|
+
const parseDate2 = (str) => {
|
|
13677
13763
|
const parts = str.split("/");
|
|
13678
13764
|
if (parts.length === 3) {
|
|
13679
13765
|
const day = parseInt(parts[0], 10);
|
|
@@ -13690,7 +13776,7 @@ function XViewScene({
|
|
|
13690
13776
|
if (!dateProp) return;
|
|
13691
13777
|
let nodeInfo = { mesh, type: "point", label: "" };
|
|
13692
13778
|
if (dateProp.date) {
|
|
13693
|
-
const date =
|
|
13779
|
+
const date = parseDate2(dateProp.date);
|
|
13694
13780
|
if (date) {
|
|
13695
13781
|
nodeInfo.startDate = date;
|
|
13696
13782
|
nodeInfo.endDate = date;
|
|
@@ -13932,16 +14018,8 @@ function XViewScene({
|
|
|
13932
14018
|
);
|
|
13933
14019
|
const handleActivateQuestLens = (0, import_react28.useCallback)(({ assigneeId, status: status2 }) => {
|
|
13934
14020
|
var _a2;
|
|
13935
|
-
const { nodeObjects, tweenGroup, graphGroup
|
|
14021
|
+
const { nodeObjects, tweenGroup, graphGroup } = stateRef.current;
|
|
13936
14022
|
if (!nodeObjects || !tweenGroup || !graphGroup) return;
|
|
13937
|
-
Object.values(nodeObjects).forEach((mesh) => {
|
|
13938
|
-
const oldLabel = mesh.getObjectByName("questDateLabel") || mesh.getObjectByName("timelineLabel");
|
|
13939
|
-
if (oldLabel) {
|
|
13940
|
-
mesh.remove(oldLabel);
|
|
13941
|
-
if (oldLabel.material.map) oldLabel.material.map.dispose();
|
|
13942
|
-
oldLabel.material.dispose();
|
|
13943
|
-
}
|
|
13944
|
-
});
|
|
13945
14023
|
const allQuests = ((_a2 = sceneDataRef.current) == null ? void 0 : _a2.quest_nodes) || [];
|
|
13946
14024
|
const filteredQuests = allQuests.filter((q) => {
|
|
13947
14025
|
const matchAssignee = !assigneeId || String(q.assignee_id) === String(assigneeId);
|
|
@@ -13963,76 +14041,91 @@ function XViewScene({
|
|
|
13963
14041
|
questsByStatus[q.status].push(q);
|
|
13964
14042
|
}
|
|
13965
14043
|
});
|
|
13966
|
-
const parseDate = (str) => {
|
|
13967
|
-
if (!str) return null;
|
|
13968
|
-
const parts = str.split("/");
|
|
13969
|
-
if (parts.length === 3) {
|
|
13970
|
-
const day = parseInt(parts[0], 10);
|
|
13971
|
-
const month = parseInt(parts[1], 10) - 1;
|
|
13972
|
-
const year = parseInt(parts[2], 10);
|
|
13973
|
-
if (!isNaN(day) && !isNaN(month) && !isNaN(year)) {
|
|
13974
|
-
return new Date(year, month, day);
|
|
13975
|
-
}
|
|
13976
|
-
}
|
|
13977
|
-
return null;
|
|
13978
|
-
};
|
|
13979
|
-
const timePoints = /* @__PURE__ */ new Set();
|
|
13980
14044
|
const questTimeInfos = /* @__PURE__ */ new Map();
|
|
14045
|
+
const allActiveTimePoints = /* @__PURE__ */ new Set();
|
|
13981
14046
|
filteredQuests.forEach((q) => {
|
|
13982
|
-
const
|
|
13983
|
-
|
|
13984
|
-
if (
|
|
13985
|
-
|
|
13986
|
-
|
|
13987
|
-
|
|
13988
|
-
info = { startDate: d, endDate: d, label: dateProp.date, isUndated: false };
|
|
13989
|
-
timePoints.add(d.getTime());
|
|
13990
|
-
}
|
|
13991
|
-
} else if (dateProp.year) {
|
|
13992
|
-
const y = parseInt(dateProp.year, 10);
|
|
13993
|
-
if (!isNaN(y)) {
|
|
13994
|
-
const d = new Date(y, 0, 1);
|
|
13995
|
-
info = { startDate: d, endDate: d, label: String(y), isUndated: false };
|
|
13996
|
-
timePoints.add(d.getTime());
|
|
13997
|
-
}
|
|
13998
|
-
} else if (dateProp.date_interval && dateProp.date_interval.start) {
|
|
13999
|
-
const sY = parseInt(dateProp.date_interval.start, 10);
|
|
14000
|
-
const eY = parseInt(dateProp.date_interval.end, 10) || sY;
|
|
14001
|
-
if (!isNaN(sY)) {
|
|
14002
|
-
const sd = new Date(sY, 0, 1);
|
|
14003
|
-
const ed = new Date(eY, 11, 31);
|
|
14004
|
-
info = { startDate: sd, endDate: ed, label: `${sY}-${eY}`, isUndated: false };
|
|
14005
|
-
timePoints.add(sd.getTime());
|
|
14006
|
-
timePoints.add(ed.getTime());
|
|
14007
|
-
}
|
|
14047
|
+
const info = parseDateProp(q.Date);
|
|
14048
|
+
questTimeInfos.set(String(q.id), info);
|
|
14049
|
+
if (!info.isUndated) {
|
|
14050
|
+
allActiveTimePoints.add(info.startDate.getTime());
|
|
14051
|
+
if (info.endDate && info.type === "interval") {
|
|
14052
|
+
allActiveTimePoints.add(info.endDate.getTime());
|
|
14008
14053
|
}
|
|
14009
14054
|
}
|
|
14010
|
-
questTimeInfos.set(String(q.id), info);
|
|
14011
14055
|
});
|
|
14012
|
-
const sortedTimePoints = Array.from(
|
|
14056
|
+
const sortedTimePoints = Array.from(allActiveTimePoints).sort((a, b) => a - b);
|
|
14013
14057
|
const timeToYMap = /* @__PURE__ */ new Map();
|
|
14014
|
-
|
|
14015
|
-
|
|
14016
|
-
|
|
14017
|
-
timeToYMap.set(t, (i - maxIdx) * (QUEST_LENS_ROW_SPACING || 30));
|
|
14018
|
-
});
|
|
14019
|
-
}
|
|
14058
|
+
sortedTimePoints.forEach((ms, idx) => {
|
|
14059
|
+
timeToYMap.set(ms, idx * TIMELINE_LAYER_SPACING_Y);
|
|
14060
|
+
});
|
|
14020
14061
|
const startX = -((QUEST_STATUS_ORDER.length - 1) * QUEST_LENS_COLUMN_SPACING) / 2;
|
|
14021
|
-
|
|
14022
|
-
|
|
14023
|
-
|
|
14024
|
-
|
|
14025
|
-
)
|
|
14026
|
-
|
|
14027
|
-
|
|
14028
|
-
|
|
14029
|
-
|
|
14030
|
-
|
|
14031
|
-
|
|
14032
|
-
|
|
14033
|
-
mesh.userData.labelObject.visible = false;
|
|
14062
|
+
const positionGroups = /* @__PURE__ */ new Map();
|
|
14063
|
+
const NODE_X_GAP = 22;
|
|
14064
|
+
QUEST_STATUS_ORDER.forEach((statusName) => {
|
|
14065
|
+
const questsInCol = questsByStatus[statusName];
|
|
14066
|
+
questsInCol.forEach((q, rowIndex) => {
|
|
14067
|
+
const timeInfo = questTimeInfos.get(String(q.id)) || { isUndated: true };
|
|
14068
|
+
let nodeY;
|
|
14069
|
+
if (!timeInfo.isUndated) {
|
|
14070
|
+
nodeY = timeToYMap.get(timeInfo.startDate.getTime());
|
|
14071
|
+
} else {
|
|
14072
|
+
const undatedOffset = sortedTimePoints.length > 0 ? sortedTimePoints.length * 5 : 0;
|
|
14073
|
+
nodeY = -40 - rowIndex * QUEST_LENS_ROW_SPACING - undatedOffset;
|
|
14034
14074
|
}
|
|
14035
|
-
|
|
14075
|
+
const posKey = `${statusName}_${nodeY}`;
|
|
14076
|
+
if (!positionGroups.has(posKey)) positionGroups.set(posKey, []);
|
|
14077
|
+
positionGroups.get(posKey).push(String(q.id));
|
|
14078
|
+
});
|
|
14079
|
+
});
|
|
14080
|
+
Object.values(nodeObjects).forEach((mesh) => {
|
|
14081
|
+
const oldLabel = mesh.getObjectByName("questDateLabel") || mesh.getObjectByName("timelineLabel");
|
|
14082
|
+
if (oldLabel) {
|
|
14083
|
+
mesh.remove(oldLabel);
|
|
14084
|
+
if (oldLabel.material) oldLabel.material.dispose();
|
|
14085
|
+
}
|
|
14086
|
+
if (mesh.userData.timelineIntervalBar) {
|
|
14087
|
+
if (graphGroup) graphGroup.remove(mesh.userData.timelineIntervalBar);
|
|
14088
|
+
mesh.userData.timelineIntervalBar = null;
|
|
14089
|
+
}
|
|
14090
|
+
if (mesh.userData.timelineEndLabel) {
|
|
14091
|
+
if (graphGroup) graphGroup.remove(mesh.userData.timelineEndLabel);
|
|
14092
|
+
mesh.userData.timelineEndLabel = null;
|
|
14093
|
+
}
|
|
14094
|
+
});
|
|
14095
|
+
const nonFilteredNodeIds = Object.keys(nodeObjects).filter((id) => !filteredQuests.some((q) => String(q.id) === String(id)));
|
|
14096
|
+
const COMMON_START_X = startX - 100;
|
|
14097
|
+
const COMMON_COL_SPACING = 30;
|
|
14098
|
+
const COMMON_ROW_SPACING = 35;
|
|
14099
|
+
const MAX_COMMON_ROWS = 15;
|
|
14100
|
+
nonFilteredNodeIds.forEach((id, idx) => {
|
|
14101
|
+
const mesh = nodeObjects[id];
|
|
14102
|
+
if (!mesh) return;
|
|
14103
|
+
const col = Math.floor(idx / MAX_COMMON_ROWS);
|
|
14104
|
+
const row = idx % MAX_COMMON_ROWS;
|
|
14105
|
+
const targetX = COMMON_START_X - col * COMMON_COL_SPACING;
|
|
14106
|
+
const targetY = -(row * COMMON_ROW_SPACING) + 50;
|
|
14107
|
+
const targetZ = 0;
|
|
14108
|
+
if (mesh.material) {
|
|
14109
|
+
const opacityTween = new import_tween2.Tween(mesh.material).to({ opacity: 1 }, 1200).easing(import_tween2.Easing.Cubic.Out);
|
|
14110
|
+
tweenGroup.add(opacityTween);
|
|
14111
|
+
opacityTween.start();
|
|
14112
|
+
}
|
|
14113
|
+
if (mesh.userData.labelObject) {
|
|
14114
|
+
mesh.userData.labelObject.visible = true;
|
|
14115
|
+
const labelTargetPos = new THREE3.Vector3(targetX, targetY, targetZ).add(
|
|
14116
|
+
mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0)
|
|
14117
|
+
);
|
|
14118
|
+
const labelTween = new import_tween2.Tween(mesh.userData.labelObject.position).to(labelTargetPos, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
14119
|
+
tweenGroup.add(labelTween);
|
|
14120
|
+
labelTween.start();
|
|
14121
|
+
}
|
|
14122
|
+
const sideTween = new import_tween2.Tween(mesh.position).to({ x: targetX, y: targetY, z: targetZ }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
14123
|
+
tweenGroup.add(sideTween);
|
|
14124
|
+
sideTween.start();
|
|
14125
|
+
});
|
|
14126
|
+
filteredQuests.forEach((q) => {
|
|
14127
|
+
const mesh = nodeObjects[String(q.id)];
|
|
14128
|
+
if (mesh) {
|
|
14036
14129
|
if (mesh.material) {
|
|
14037
14130
|
const fadeInTween = new import_tween2.Tween(mesh.material).to({ opacity: 1 }, 1200).easing(import_tween2.Easing.Cubic.Out);
|
|
14038
14131
|
tweenGroup.add(fadeInTween);
|
|
@@ -14050,29 +14143,66 @@ function XViewScene({
|
|
|
14050
14143
|
questsInCol.forEach((q, rowIndex) => {
|
|
14051
14144
|
const nodeId = String(q.id);
|
|
14052
14145
|
let mesh = nodeObjects[nodeId];
|
|
14053
|
-
if (!mesh) {
|
|
14054
|
-
mesh = addOrUpdateNodeMesh(q, new THREE3.Vector3(colX, 150, 0), true);
|
|
14055
|
-
}
|
|
14056
14146
|
const timeInfo = questTimeInfos.get(nodeId) || { isUndated: true };
|
|
14057
14147
|
let targetY;
|
|
14058
14148
|
if (!timeInfo.isUndated) {
|
|
14059
14149
|
targetY = timeToYMap.get(timeInfo.startDate.getTime());
|
|
14060
14150
|
} else {
|
|
14061
14151
|
const undatedOffset = sortedTimePoints.length > 0 ? sortedTimePoints.length * 5 : 0;
|
|
14062
|
-
targetY = -
|
|
14152
|
+
targetY = -40 - rowIndex * QUEST_LENS_ROW_SPACING - undatedOffset;
|
|
14063
14153
|
}
|
|
14064
|
-
const
|
|
14154
|
+
const posKey = `${statusName}_${targetY}`;
|
|
14155
|
+
const group = positionGroups.get(posKey) || [nodeId];
|
|
14156
|
+
const indexInGroup = group.indexOf(nodeId);
|
|
14157
|
+
const xOffset = (indexInGroup - (group.length - 1) / 2) * NODE_X_GAP;
|
|
14158
|
+
const finalX = colX + xOffset;
|
|
14159
|
+
if (!mesh) {
|
|
14160
|
+
mesh = addOrUpdateNodeMesh(q, new THREE3.Vector3(finalX, 150, 0), true);
|
|
14161
|
+
}
|
|
14162
|
+
const lensTween = new import_tween2.Tween(mesh.position).to({ x: finalX, y: targetY, z: 0 }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
14065
14163
|
tweenGroup.add(lensTween);
|
|
14066
14164
|
lensTween.start();
|
|
14067
|
-
if (!timeInfo.isUndated && timeInfo.label) {
|
|
14165
|
+
if (!timeInfo.isUndated && timeInfo.label && !mesh.getObjectByName("questDateLabel")) {
|
|
14068
14166
|
const dateSprite = createTextSprite(timeInfo.label, 36);
|
|
14069
14167
|
dateSprite.name = "questDateLabel";
|
|
14070
14168
|
dateSprite.position.set(0, -5.5, 0);
|
|
14071
14169
|
mesh.add(dateSprite);
|
|
14072
14170
|
}
|
|
14171
|
+
if (timeInfo.type === "interval" && timeToYMap.has(timeInfo.endDate.getTime())) {
|
|
14172
|
+
const endY = timeToYMap.get(timeInfo.endDate.getTime());
|
|
14173
|
+
if (Math.abs(endY - targetY) > 0.1) {
|
|
14174
|
+
const barHeight = Math.abs(endY - targetY);
|
|
14175
|
+
const barGeometry = new THREE3.CylinderGeometry(
|
|
14176
|
+
TIMELINE_INTERVAL_BAR_RADIUS,
|
|
14177
|
+
TIMELINE_INTERVAL_BAR_RADIUS,
|
|
14178
|
+
1,
|
|
14179
|
+
16
|
|
14180
|
+
);
|
|
14181
|
+
const barMaterial = new THREE3.MeshStandardMaterial({
|
|
14182
|
+
color: TIMELINE_GOLD_COLOR,
|
|
14183
|
+
emissive: 12092939,
|
|
14184
|
+
emissiveIntensity: 0.4,
|
|
14185
|
+
transparent: true,
|
|
14186
|
+
opacity: TIMELINE_INTERVAL_BAR_OPACITY,
|
|
14187
|
+
roughness: 0.3,
|
|
14188
|
+
metalness: 0.8
|
|
14189
|
+
});
|
|
14190
|
+
const intervalBar = new THREE3.Mesh(barGeometry, barMaterial);
|
|
14191
|
+
intervalBar.userData.associatedNodeId = mesh.userData.id;
|
|
14192
|
+
intervalBar.position.set(finalX, (targetY + endY) / 2, -0.5);
|
|
14193
|
+
intervalBar.scale.y = barHeight;
|
|
14194
|
+
graphGroup.add(intervalBar);
|
|
14195
|
+
mesh.userData.timelineIntervalBar = intervalBar;
|
|
14196
|
+
const endLabel = createTextSprite(timeInfo.label.split(" - ")[1] || "", 30);
|
|
14197
|
+
endLabel.name = "timelineEndLabel";
|
|
14198
|
+
endLabel.position.set(finalX, endY + 4, 0);
|
|
14199
|
+
graphGroup.add(endLabel);
|
|
14200
|
+
mesh.userData.timelineEndLabel = endLabel;
|
|
14201
|
+
}
|
|
14202
|
+
}
|
|
14073
14203
|
if (mesh.userData.labelObject) {
|
|
14074
|
-
const labelTargetPos = new THREE3.Vector3(
|
|
14075
|
-
mesh.userData.labelOffset || new THREE3.Vector3(0,
|
|
14204
|
+
const labelTargetPos = new THREE3.Vector3(finalX, targetY, 0).add(
|
|
14205
|
+
mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0)
|
|
14076
14206
|
);
|
|
14077
14207
|
const labelTween = new import_tween2.Tween(mesh.userData.labelObject.position).to(labelTargetPos, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
14078
14208
|
tweenGroup.add(labelTween);
|
package/dist/index.mjs
CHANGED
|
@@ -1295,6 +1295,15 @@ var createNodeMesh = (nodeData, position, glowTexture) => {
|
|
|
1295
1295
|
label.name = "label";
|
|
1296
1296
|
mesh.userData.labelObject = label;
|
|
1297
1297
|
mesh.userData.labelOffset = new THREE.Vector3(0, 3.8, 0);
|
|
1298
|
+
if (nodeData.is_quest && nodeData.Date) {
|
|
1299
|
+
const timeInfo = parseDateProp(nodeData.Date);
|
|
1300
|
+
if (!timeInfo.isUndated && timeInfo.label) {
|
|
1301
|
+
const dateSprite = createTextSprite(timeInfo.label, 36);
|
|
1302
|
+
dateSprite.name = "questDateLabel";
|
|
1303
|
+
dateSprite.position.set(0, -5.5, 0);
|
|
1304
|
+
mesh.add(dateSprite);
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1298
1307
|
return mesh;
|
|
1299
1308
|
};
|
|
1300
1309
|
var updateExistingNodeVisuals = (state, updatedNode) => {
|
|
@@ -3282,9 +3291,14 @@ var userActionHandlers = {
|
|
|
3282
3291
|
};
|
|
3283
3292
|
specificParentData.nodes.push(nextQuestNode);
|
|
3284
3293
|
if (stateRef.current.nodeObjects[String(nodeToSave.id)]) {
|
|
3285
|
-
const
|
|
3286
|
-
|
|
3287
|
-
|
|
3294
|
+
const oldMeshPosition = stateRef.current.nodeObjects[String(nodeToSave.id)].position.clone();
|
|
3295
|
+
setTimeout(() => {
|
|
3296
|
+
if (stateRef.current && stateRef.current.graphGroup) {
|
|
3297
|
+
const pos = oldMeshPosition.clone();
|
|
3298
|
+
pos.x += 12;
|
|
3299
|
+
addStandaloneNodeToScene(stateRef.current, nextQuestNode, pos);
|
|
3300
|
+
}
|
|
3301
|
+
}, 2e3);
|
|
3288
3302
|
}
|
|
3289
3303
|
}
|
|
3290
3304
|
}
|
|
@@ -4227,6 +4241,78 @@ function calculateNextRecurrenceDate(config) {
|
|
|
4227
4241
|
confirmed: true
|
|
4228
4242
|
};
|
|
4229
4243
|
}
|
|
4244
|
+
var parseDate = (str) => {
|
|
4245
|
+
if (!str) return null;
|
|
4246
|
+
const parts = str.split("/");
|
|
4247
|
+
if (parts.length === 3) {
|
|
4248
|
+
const day = parseInt(parts[0], 10);
|
|
4249
|
+
const month = parseInt(parts[1], 10) - 1;
|
|
4250
|
+
const year = parseInt(parts[2], 10);
|
|
4251
|
+
if (!isNaN(day) && !isNaN(month) && !isNaN(year)) {
|
|
4252
|
+
return new Date(year, month, day);
|
|
4253
|
+
}
|
|
4254
|
+
}
|
|
4255
|
+
return null;
|
|
4256
|
+
};
|
|
4257
|
+
var parseDateProp = (dateProp) => {
|
|
4258
|
+
let info = { isUndated: true, label: "", type: "point" };
|
|
4259
|
+
if (!dateProp) return info;
|
|
4260
|
+
if (dateProp.type === "Data") {
|
|
4261
|
+
const d = parseDate(dateProp.value);
|
|
4262
|
+
if (d) {
|
|
4263
|
+
info = { startDate: d, endDate: d, label: dateProp.value, type: "point", isUndated: false };
|
|
4264
|
+
}
|
|
4265
|
+
} else if (dateProp.type === "Date Interval" || dateProp.type === "Date Range" || dateProp.type === "interval") {
|
|
4266
|
+
const sd = parseDate(dateProp.start || dateProp.value);
|
|
4267
|
+
const ed = parseDate(dateProp.end);
|
|
4268
|
+
if (sd) {
|
|
4269
|
+
info = {
|
|
4270
|
+
startDate: sd,
|
|
4271
|
+
endDate: ed || sd,
|
|
4272
|
+
label: `${dateProp.start || dateProp.value}${ed ? " - " + dateProp.end : ""}`,
|
|
4273
|
+
type: ed ? "interval" : "point",
|
|
4274
|
+
isUndated: false
|
|
4275
|
+
};
|
|
4276
|
+
}
|
|
4277
|
+
} else if (dateProp.date) {
|
|
4278
|
+
const d = parseDate(dateProp.date);
|
|
4279
|
+
if (d)
|
|
4280
|
+
info = {
|
|
4281
|
+
startDate: d,
|
|
4282
|
+
endDate: d,
|
|
4283
|
+
label: dateProp.date,
|
|
4284
|
+
type: "point",
|
|
4285
|
+
isUndated: false
|
|
4286
|
+
};
|
|
4287
|
+
} else if (dateProp.year) {
|
|
4288
|
+
const y = parseInt(dateProp.year, 10);
|
|
4289
|
+
if (!isNaN(y)) {
|
|
4290
|
+
const d = new Date(y, 0, 1);
|
|
4291
|
+
info = {
|
|
4292
|
+
startDate: d,
|
|
4293
|
+
endDate: d,
|
|
4294
|
+
label: String(y),
|
|
4295
|
+
type: "point",
|
|
4296
|
+
isUndated: false
|
|
4297
|
+
};
|
|
4298
|
+
}
|
|
4299
|
+
} else if (dateProp.date_interval && dateProp.date_interval.start) {
|
|
4300
|
+
const sY = parseInt(dateProp.date_interval.start, 10);
|
|
4301
|
+
const eY = parseInt(dateProp.date_interval.end, 10) || sY;
|
|
4302
|
+
if (!isNaN(sY)) {
|
|
4303
|
+
const sd = new Date(sY, 0, 1);
|
|
4304
|
+
const ed = new Date(eY, 11, 31);
|
|
4305
|
+
info = {
|
|
4306
|
+
startDate: sd,
|
|
4307
|
+
endDate: ed,
|
|
4308
|
+
label: `${sY} - ${eY}`,
|
|
4309
|
+
type: "interval",
|
|
4310
|
+
isUndated: false
|
|
4311
|
+
};
|
|
4312
|
+
}
|
|
4313
|
+
}
|
|
4314
|
+
return info;
|
|
4315
|
+
};
|
|
4230
4316
|
|
|
4231
4317
|
// src/components/CustomPropertyDisplay.jsx
|
|
4232
4318
|
import React3, { useState as useState4, useRef as useRef3, useEffect as useEffect3 } from "react";
|
|
@@ -9491,7 +9577,7 @@ function InSceneQuestForm({
|
|
|
9491
9577
|
textureImageUrl: null,
|
|
9492
9578
|
reviewStack,
|
|
9493
9579
|
timeline: initialTimeline,
|
|
9494
|
-
Date: questDate,
|
|
9580
|
+
Date: questDate ? { ...questDate, confirmed: true } : null,
|
|
9495
9581
|
recurrence_config: recurrenceConfig,
|
|
9496
9582
|
...additionalData
|
|
9497
9583
|
});
|
|
@@ -10967,7 +11053,7 @@ ${noteText}` : noteText : entry.notes,
|
|
|
10967
11053
|
description_sections: processedSections,
|
|
10968
11054
|
intensity,
|
|
10969
11055
|
recurrence_config: currentRecurrenceConfig,
|
|
10970
|
-
Date: questDate,
|
|
11056
|
+
Date: questDate ? { ...questDate, confirmed: true } : null,
|
|
10971
11057
|
useImageAsTexture: false,
|
|
10972
11058
|
textureImageUrl: null,
|
|
10973
11059
|
is_quest: true,
|
|
@@ -13543,7 +13629,7 @@ function XViewScene({
|
|
|
13543
13629
|
}
|
|
13544
13630
|
}
|
|
13545
13631
|
Object.values(nodeObjects).forEach((mesh) => {
|
|
13546
|
-
const oldLabel = mesh.getObjectByName("timelineLabel")
|
|
13632
|
+
const oldLabel = mesh.getObjectByName("timelineLabel");
|
|
13547
13633
|
if (oldLabel) {
|
|
13548
13634
|
mesh.remove(oldLabel);
|
|
13549
13635
|
if (oldLabel.material.map) oldLabel.material.map.dispose();
|
|
@@ -13554,7 +13640,7 @@ function XViewScene({
|
|
|
13554
13640
|
});
|
|
13555
13641
|
const timelineNodes = [];
|
|
13556
13642
|
const allTimePoints = /* @__PURE__ */ new Set();
|
|
13557
|
-
const
|
|
13643
|
+
const parseDate2 = (str) => {
|
|
13558
13644
|
const parts = str.split("/");
|
|
13559
13645
|
if (parts.length === 3) {
|
|
13560
13646
|
const day = parseInt(parts[0], 10);
|
|
@@ -13571,7 +13657,7 @@ function XViewScene({
|
|
|
13571
13657
|
let nodeInfo = { mesh, type: "point", label: "", isUndated: true };
|
|
13572
13658
|
if (dateProp) {
|
|
13573
13659
|
if (dateProp.date) {
|
|
13574
|
-
const date =
|
|
13660
|
+
const date = parseDate2(dateProp.date);
|
|
13575
13661
|
if (date) {
|
|
13576
13662
|
nodeInfo.startDate = date;
|
|
13577
13663
|
nodeInfo.endDate = date;
|
|
@@ -13717,7 +13803,7 @@ function XViewScene({
|
|
|
13717
13803
|
});
|
|
13718
13804
|
const timelineNodes = [];
|
|
13719
13805
|
const allTimePoints = /* @__PURE__ */ new Set();
|
|
13720
|
-
const
|
|
13806
|
+
const parseDate2 = (str) => {
|
|
13721
13807
|
const parts = str.split("/");
|
|
13722
13808
|
if (parts.length === 3) {
|
|
13723
13809
|
const day = parseInt(parts[0], 10);
|
|
@@ -13734,7 +13820,7 @@ function XViewScene({
|
|
|
13734
13820
|
if (!dateProp) return;
|
|
13735
13821
|
let nodeInfo = { mesh, type: "point", label: "" };
|
|
13736
13822
|
if (dateProp.date) {
|
|
13737
|
-
const date =
|
|
13823
|
+
const date = parseDate2(dateProp.date);
|
|
13738
13824
|
if (date) {
|
|
13739
13825
|
nodeInfo.startDate = date;
|
|
13740
13826
|
nodeInfo.endDate = date;
|
|
@@ -13976,16 +14062,8 @@ function XViewScene({
|
|
|
13976
14062
|
);
|
|
13977
14063
|
const handleActivateQuestLens = useCallback4(({ assigneeId, status: status2 }) => {
|
|
13978
14064
|
var _a2;
|
|
13979
|
-
const { nodeObjects, tweenGroup, graphGroup
|
|
14065
|
+
const { nodeObjects, tweenGroup, graphGroup } = stateRef.current;
|
|
13980
14066
|
if (!nodeObjects || !tweenGroup || !graphGroup) return;
|
|
13981
|
-
Object.values(nodeObjects).forEach((mesh) => {
|
|
13982
|
-
const oldLabel = mesh.getObjectByName("questDateLabel") || mesh.getObjectByName("timelineLabel");
|
|
13983
|
-
if (oldLabel) {
|
|
13984
|
-
mesh.remove(oldLabel);
|
|
13985
|
-
if (oldLabel.material.map) oldLabel.material.map.dispose();
|
|
13986
|
-
oldLabel.material.dispose();
|
|
13987
|
-
}
|
|
13988
|
-
});
|
|
13989
14067
|
const allQuests = ((_a2 = sceneDataRef.current) == null ? void 0 : _a2.quest_nodes) || [];
|
|
13990
14068
|
const filteredQuests = allQuests.filter((q) => {
|
|
13991
14069
|
const matchAssignee = !assigneeId || String(q.assignee_id) === String(assigneeId);
|
|
@@ -14007,76 +14085,91 @@ function XViewScene({
|
|
|
14007
14085
|
questsByStatus[q.status].push(q);
|
|
14008
14086
|
}
|
|
14009
14087
|
});
|
|
14010
|
-
const parseDate = (str) => {
|
|
14011
|
-
if (!str) return null;
|
|
14012
|
-
const parts = str.split("/");
|
|
14013
|
-
if (parts.length === 3) {
|
|
14014
|
-
const day = parseInt(parts[0], 10);
|
|
14015
|
-
const month = parseInt(parts[1], 10) - 1;
|
|
14016
|
-
const year = parseInt(parts[2], 10);
|
|
14017
|
-
if (!isNaN(day) && !isNaN(month) && !isNaN(year)) {
|
|
14018
|
-
return new Date(year, month, day);
|
|
14019
|
-
}
|
|
14020
|
-
}
|
|
14021
|
-
return null;
|
|
14022
|
-
};
|
|
14023
|
-
const timePoints = /* @__PURE__ */ new Set();
|
|
14024
14088
|
const questTimeInfos = /* @__PURE__ */ new Map();
|
|
14089
|
+
const allActiveTimePoints = /* @__PURE__ */ new Set();
|
|
14025
14090
|
filteredQuests.forEach((q) => {
|
|
14026
|
-
const
|
|
14027
|
-
|
|
14028
|
-
if (
|
|
14029
|
-
|
|
14030
|
-
|
|
14031
|
-
|
|
14032
|
-
info = { startDate: d, endDate: d, label: dateProp.date, isUndated: false };
|
|
14033
|
-
timePoints.add(d.getTime());
|
|
14034
|
-
}
|
|
14035
|
-
} else if (dateProp.year) {
|
|
14036
|
-
const y = parseInt(dateProp.year, 10);
|
|
14037
|
-
if (!isNaN(y)) {
|
|
14038
|
-
const d = new Date(y, 0, 1);
|
|
14039
|
-
info = { startDate: d, endDate: d, label: String(y), isUndated: false };
|
|
14040
|
-
timePoints.add(d.getTime());
|
|
14041
|
-
}
|
|
14042
|
-
} else if (dateProp.date_interval && dateProp.date_interval.start) {
|
|
14043
|
-
const sY = parseInt(dateProp.date_interval.start, 10);
|
|
14044
|
-
const eY = parseInt(dateProp.date_interval.end, 10) || sY;
|
|
14045
|
-
if (!isNaN(sY)) {
|
|
14046
|
-
const sd = new Date(sY, 0, 1);
|
|
14047
|
-
const ed = new Date(eY, 11, 31);
|
|
14048
|
-
info = { startDate: sd, endDate: ed, label: `${sY}-${eY}`, isUndated: false };
|
|
14049
|
-
timePoints.add(sd.getTime());
|
|
14050
|
-
timePoints.add(ed.getTime());
|
|
14051
|
-
}
|
|
14091
|
+
const info = parseDateProp(q.Date);
|
|
14092
|
+
questTimeInfos.set(String(q.id), info);
|
|
14093
|
+
if (!info.isUndated) {
|
|
14094
|
+
allActiveTimePoints.add(info.startDate.getTime());
|
|
14095
|
+
if (info.endDate && info.type === "interval") {
|
|
14096
|
+
allActiveTimePoints.add(info.endDate.getTime());
|
|
14052
14097
|
}
|
|
14053
14098
|
}
|
|
14054
|
-
questTimeInfos.set(String(q.id), info);
|
|
14055
14099
|
});
|
|
14056
|
-
const sortedTimePoints = Array.from(
|
|
14100
|
+
const sortedTimePoints = Array.from(allActiveTimePoints).sort((a, b) => a - b);
|
|
14057
14101
|
const timeToYMap = /* @__PURE__ */ new Map();
|
|
14058
|
-
|
|
14059
|
-
|
|
14060
|
-
|
|
14061
|
-
timeToYMap.set(t, (i - maxIdx) * (QUEST_LENS_ROW_SPACING || 30));
|
|
14062
|
-
});
|
|
14063
|
-
}
|
|
14102
|
+
sortedTimePoints.forEach((ms, idx) => {
|
|
14103
|
+
timeToYMap.set(ms, idx * TIMELINE_LAYER_SPACING_Y);
|
|
14104
|
+
});
|
|
14064
14105
|
const startX = -((QUEST_STATUS_ORDER.length - 1) * QUEST_LENS_COLUMN_SPACING) / 2;
|
|
14065
|
-
|
|
14066
|
-
|
|
14067
|
-
|
|
14068
|
-
|
|
14069
|
-
)
|
|
14070
|
-
|
|
14071
|
-
|
|
14072
|
-
|
|
14073
|
-
|
|
14074
|
-
|
|
14075
|
-
|
|
14076
|
-
|
|
14077
|
-
mesh.userData.labelObject.visible = false;
|
|
14106
|
+
const positionGroups = /* @__PURE__ */ new Map();
|
|
14107
|
+
const NODE_X_GAP = 22;
|
|
14108
|
+
QUEST_STATUS_ORDER.forEach((statusName) => {
|
|
14109
|
+
const questsInCol = questsByStatus[statusName];
|
|
14110
|
+
questsInCol.forEach((q, rowIndex) => {
|
|
14111
|
+
const timeInfo = questTimeInfos.get(String(q.id)) || { isUndated: true };
|
|
14112
|
+
let nodeY;
|
|
14113
|
+
if (!timeInfo.isUndated) {
|
|
14114
|
+
nodeY = timeToYMap.get(timeInfo.startDate.getTime());
|
|
14115
|
+
} else {
|
|
14116
|
+
const undatedOffset = sortedTimePoints.length > 0 ? sortedTimePoints.length * 5 : 0;
|
|
14117
|
+
nodeY = -40 - rowIndex * QUEST_LENS_ROW_SPACING - undatedOffset;
|
|
14078
14118
|
}
|
|
14079
|
-
|
|
14119
|
+
const posKey = `${statusName}_${nodeY}`;
|
|
14120
|
+
if (!positionGroups.has(posKey)) positionGroups.set(posKey, []);
|
|
14121
|
+
positionGroups.get(posKey).push(String(q.id));
|
|
14122
|
+
});
|
|
14123
|
+
});
|
|
14124
|
+
Object.values(nodeObjects).forEach((mesh) => {
|
|
14125
|
+
const oldLabel = mesh.getObjectByName("questDateLabel") || mesh.getObjectByName("timelineLabel");
|
|
14126
|
+
if (oldLabel) {
|
|
14127
|
+
mesh.remove(oldLabel);
|
|
14128
|
+
if (oldLabel.material) oldLabel.material.dispose();
|
|
14129
|
+
}
|
|
14130
|
+
if (mesh.userData.timelineIntervalBar) {
|
|
14131
|
+
if (graphGroup) graphGroup.remove(mesh.userData.timelineIntervalBar);
|
|
14132
|
+
mesh.userData.timelineIntervalBar = null;
|
|
14133
|
+
}
|
|
14134
|
+
if (mesh.userData.timelineEndLabel) {
|
|
14135
|
+
if (graphGroup) graphGroup.remove(mesh.userData.timelineEndLabel);
|
|
14136
|
+
mesh.userData.timelineEndLabel = null;
|
|
14137
|
+
}
|
|
14138
|
+
});
|
|
14139
|
+
const nonFilteredNodeIds = Object.keys(nodeObjects).filter((id) => !filteredQuests.some((q) => String(q.id) === String(id)));
|
|
14140
|
+
const COMMON_START_X = startX - 100;
|
|
14141
|
+
const COMMON_COL_SPACING = 30;
|
|
14142
|
+
const COMMON_ROW_SPACING = 35;
|
|
14143
|
+
const MAX_COMMON_ROWS = 15;
|
|
14144
|
+
nonFilteredNodeIds.forEach((id, idx) => {
|
|
14145
|
+
const mesh = nodeObjects[id];
|
|
14146
|
+
if (!mesh) return;
|
|
14147
|
+
const col = Math.floor(idx / MAX_COMMON_ROWS);
|
|
14148
|
+
const row = idx % MAX_COMMON_ROWS;
|
|
14149
|
+
const targetX = COMMON_START_X - col * COMMON_COL_SPACING;
|
|
14150
|
+
const targetY = -(row * COMMON_ROW_SPACING) + 50;
|
|
14151
|
+
const targetZ = 0;
|
|
14152
|
+
if (mesh.material) {
|
|
14153
|
+
const opacityTween = new Tween2(mesh.material).to({ opacity: 1 }, 1200).easing(Easing2.Cubic.Out);
|
|
14154
|
+
tweenGroup.add(opacityTween);
|
|
14155
|
+
opacityTween.start();
|
|
14156
|
+
}
|
|
14157
|
+
if (mesh.userData.labelObject) {
|
|
14158
|
+
mesh.userData.labelObject.visible = true;
|
|
14159
|
+
const labelTargetPos = new THREE3.Vector3(targetX, targetY, targetZ).add(
|
|
14160
|
+
mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0)
|
|
14161
|
+
);
|
|
14162
|
+
const labelTween = new Tween2(mesh.userData.labelObject.position).to(labelTargetPos, 1500).easing(Easing2.Cubic.InOut);
|
|
14163
|
+
tweenGroup.add(labelTween);
|
|
14164
|
+
labelTween.start();
|
|
14165
|
+
}
|
|
14166
|
+
const sideTween = new Tween2(mesh.position).to({ x: targetX, y: targetY, z: targetZ }, 1500).easing(Easing2.Cubic.InOut);
|
|
14167
|
+
tweenGroup.add(sideTween);
|
|
14168
|
+
sideTween.start();
|
|
14169
|
+
});
|
|
14170
|
+
filteredQuests.forEach((q) => {
|
|
14171
|
+
const mesh = nodeObjects[String(q.id)];
|
|
14172
|
+
if (mesh) {
|
|
14080
14173
|
if (mesh.material) {
|
|
14081
14174
|
const fadeInTween = new Tween2(mesh.material).to({ opacity: 1 }, 1200).easing(Easing2.Cubic.Out);
|
|
14082
14175
|
tweenGroup.add(fadeInTween);
|
|
@@ -14094,29 +14187,66 @@ function XViewScene({
|
|
|
14094
14187
|
questsInCol.forEach((q, rowIndex) => {
|
|
14095
14188
|
const nodeId = String(q.id);
|
|
14096
14189
|
let mesh = nodeObjects[nodeId];
|
|
14097
|
-
if (!mesh) {
|
|
14098
|
-
mesh = addOrUpdateNodeMesh(q, new THREE3.Vector3(colX, 150, 0), true);
|
|
14099
|
-
}
|
|
14100
14190
|
const timeInfo = questTimeInfos.get(nodeId) || { isUndated: true };
|
|
14101
14191
|
let targetY;
|
|
14102
14192
|
if (!timeInfo.isUndated) {
|
|
14103
14193
|
targetY = timeToYMap.get(timeInfo.startDate.getTime());
|
|
14104
14194
|
} else {
|
|
14105
14195
|
const undatedOffset = sortedTimePoints.length > 0 ? sortedTimePoints.length * 5 : 0;
|
|
14106
|
-
targetY = -
|
|
14196
|
+
targetY = -40 - rowIndex * QUEST_LENS_ROW_SPACING - undatedOffset;
|
|
14107
14197
|
}
|
|
14108
|
-
const
|
|
14198
|
+
const posKey = `${statusName}_${targetY}`;
|
|
14199
|
+
const group = positionGroups.get(posKey) || [nodeId];
|
|
14200
|
+
const indexInGroup = group.indexOf(nodeId);
|
|
14201
|
+
const xOffset = (indexInGroup - (group.length - 1) / 2) * NODE_X_GAP;
|
|
14202
|
+
const finalX = colX + xOffset;
|
|
14203
|
+
if (!mesh) {
|
|
14204
|
+
mesh = addOrUpdateNodeMesh(q, new THREE3.Vector3(finalX, 150, 0), true);
|
|
14205
|
+
}
|
|
14206
|
+
const lensTween = new Tween2(mesh.position).to({ x: finalX, y: targetY, z: 0 }, 1500).easing(Easing2.Cubic.InOut);
|
|
14109
14207
|
tweenGroup.add(lensTween);
|
|
14110
14208
|
lensTween.start();
|
|
14111
|
-
if (!timeInfo.isUndated && timeInfo.label) {
|
|
14209
|
+
if (!timeInfo.isUndated && timeInfo.label && !mesh.getObjectByName("questDateLabel")) {
|
|
14112
14210
|
const dateSprite = createTextSprite(timeInfo.label, 36);
|
|
14113
14211
|
dateSprite.name = "questDateLabel";
|
|
14114
14212
|
dateSprite.position.set(0, -5.5, 0);
|
|
14115
14213
|
mesh.add(dateSprite);
|
|
14116
14214
|
}
|
|
14215
|
+
if (timeInfo.type === "interval" && timeToYMap.has(timeInfo.endDate.getTime())) {
|
|
14216
|
+
const endY = timeToYMap.get(timeInfo.endDate.getTime());
|
|
14217
|
+
if (Math.abs(endY - targetY) > 0.1) {
|
|
14218
|
+
const barHeight = Math.abs(endY - targetY);
|
|
14219
|
+
const barGeometry = new THREE3.CylinderGeometry(
|
|
14220
|
+
TIMELINE_INTERVAL_BAR_RADIUS,
|
|
14221
|
+
TIMELINE_INTERVAL_BAR_RADIUS,
|
|
14222
|
+
1,
|
|
14223
|
+
16
|
|
14224
|
+
);
|
|
14225
|
+
const barMaterial = new THREE3.MeshStandardMaterial({
|
|
14226
|
+
color: TIMELINE_GOLD_COLOR,
|
|
14227
|
+
emissive: 12092939,
|
|
14228
|
+
emissiveIntensity: 0.4,
|
|
14229
|
+
transparent: true,
|
|
14230
|
+
opacity: TIMELINE_INTERVAL_BAR_OPACITY,
|
|
14231
|
+
roughness: 0.3,
|
|
14232
|
+
metalness: 0.8
|
|
14233
|
+
});
|
|
14234
|
+
const intervalBar = new THREE3.Mesh(barGeometry, barMaterial);
|
|
14235
|
+
intervalBar.userData.associatedNodeId = mesh.userData.id;
|
|
14236
|
+
intervalBar.position.set(finalX, (targetY + endY) / 2, -0.5);
|
|
14237
|
+
intervalBar.scale.y = barHeight;
|
|
14238
|
+
graphGroup.add(intervalBar);
|
|
14239
|
+
mesh.userData.timelineIntervalBar = intervalBar;
|
|
14240
|
+
const endLabel = createTextSprite(timeInfo.label.split(" - ")[1] || "", 30);
|
|
14241
|
+
endLabel.name = "timelineEndLabel";
|
|
14242
|
+
endLabel.position.set(finalX, endY + 4, 0);
|
|
14243
|
+
graphGroup.add(endLabel);
|
|
14244
|
+
mesh.userData.timelineEndLabel = endLabel;
|
|
14245
|
+
}
|
|
14246
|
+
}
|
|
14117
14247
|
if (mesh.userData.labelObject) {
|
|
14118
|
-
const labelTargetPos = new THREE3.Vector3(
|
|
14119
|
-
mesh.userData.labelOffset || new THREE3.Vector3(0,
|
|
14248
|
+
const labelTargetPos = new THREE3.Vector3(finalX, targetY, 0).add(
|
|
14249
|
+
mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0)
|
|
14120
14250
|
);
|
|
14121
14251
|
const labelTween = new Tween2(mesh.userData.labelObject.position).to(labelTargetPos, 1500).easing(Easing2.Cubic.InOut);
|
|
14122
14252
|
tweenGroup.add(labelTween);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lv-x-software-house/x_view",
|
|
3
|
-
"version": "1.2.5-dev.
|
|
3
|
+
"version": "1.2.5-dev.45",
|
|
4
4
|
"description": "Pacote privado contendo os componentes e lógica de renderização 3D do X View.",
|
|
5
5
|
"author": "iv.x - Engenharia de Software - ivxsoftwarehouse@gmail.com",
|
|
6
6
|
"license": "UNLICENSED",
|