@promptbook/core 0.112.0-65 → 0.112.0-66
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/esm/index.es.js +695 -62
- package/esm/index.es.js.map +1 -1
- package/esm/src/avatars/types/AvatarVisualDefinition.d.ts +1 -1
- package/esm/src/avatars/visuals/minecraft2AvatarVisual.d.ts +7 -0
- package/esm/src/avatars/visuals/minecraftAvatarVisualShared.d.ts +48 -0
- package/esm/src/cli/cli-commands/coder/ensureCoderGitignoreFile.d.ts +1 -1
- package/esm/src/config.d.ts +3 -3
- package/esm/src/utils/files/getPromptbookTempPath.d.ts +24 -0
- package/esm/src/utils/files/getPromptbookTempPath.test.d.ts +1 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/umd/index.umd.js +698 -65
- package/umd/index.umd.js.map +1 -1
- package/umd/src/avatars/types/AvatarVisualDefinition.d.ts +1 -1
- package/umd/src/avatars/visuals/minecraft2AvatarVisual.d.ts +7 -0
- package/umd/src/avatars/visuals/minecraftAvatarVisualShared.d.ts +48 -0
- package/umd/src/cli/cli-commands/coder/ensureCoderGitignoreFile.d.ts +1 -1
- package/umd/src/config.d.ts +3 -3
- package/umd/src/utils/files/getPromptbookTempPath.d.ts +24 -0
- package/umd/src/utils/files/getPromptbookTempPath.test.d.ts +1 -0
- package/umd/src/version.d.ts +1 -1
package/esm/index.es.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { SHA256 } from 'crypto-js';
|
|
2
2
|
import hexEncoder from 'crypto-js/enc-hex';
|
|
3
3
|
import { spaceTrim as spaceTrim$1 } from 'spacetrim';
|
|
4
|
+
import { posix, basename, join, dirname, isAbsolute } from 'path';
|
|
4
5
|
import { randomBytes } from 'crypto';
|
|
5
6
|
import { Subject, BehaviorSubject } from 'rxjs';
|
|
6
7
|
import { forTime } from 'waitasecond';
|
|
7
8
|
import sha256 from 'crypto-js/sha256';
|
|
8
|
-
import { basename, join, dirname, isAbsolute } from 'path';
|
|
9
9
|
import { lookup, extension } from 'mime-types';
|
|
10
10
|
import { parse, unparse } from 'papaparse';
|
|
11
11
|
import moment from 'moment';
|
|
@@ -28,7 +28,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
28
28
|
* @generated
|
|
29
29
|
* @see https://github.com/webgptorg/promptbook
|
|
30
30
|
*/
|
|
31
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
31
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-66';
|
|
32
32
|
/**
|
|
33
33
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
34
34
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -947,6 +947,29 @@ function saturate(amount) {
|
|
|
947
947
|
}
|
|
948
948
|
// TODO: Maybe implement by mix+hsl
|
|
949
949
|
|
|
950
|
+
/**
|
|
951
|
+
* Relative directory name without the `./` prefix for Git ignore rules and glob patterns.
|
|
952
|
+
*
|
|
953
|
+
* @private internal utility for Promptbook-owned temp files
|
|
954
|
+
*/
|
|
955
|
+
const PROMPTBOOK_TEMP_DIRECTORY_NAME = '.promptbook';
|
|
956
|
+
/**
|
|
957
|
+
* Builds one project-relative path inside the shared Promptbook working directory.
|
|
958
|
+
*
|
|
959
|
+
* @private internal utility for Promptbook-owned temp files
|
|
960
|
+
*/
|
|
961
|
+
function getPromptbookTempPath(...pathSegments) {
|
|
962
|
+
return `./${getPromptbookTempPosixPath(...pathSegments)}`;
|
|
963
|
+
}
|
|
964
|
+
/**
|
|
965
|
+
* Builds one POSIX path fragment inside the shared Promptbook working directory for globs and generated text files.
|
|
966
|
+
*
|
|
967
|
+
* @private internal utility for Promptbook-owned temp files
|
|
968
|
+
*/
|
|
969
|
+
function getPromptbookTempPosixPath(...pathSegments) {
|
|
970
|
+
return posix.join(PROMPTBOOK_TEMP_DIRECTORY_NAME, ...pathSegments);
|
|
971
|
+
}
|
|
972
|
+
|
|
950
973
|
/**
|
|
951
974
|
* Returns the same value that is passed as argument.
|
|
952
975
|
* No side effects.
|
|
@@ -1217,7 +1240,6 @@ const DEFAULT_BOOKS_DIRNAME = './books';
|
|
|
1217
1240
|
*/
|
|
1218
1241
|
const DEFAULT_AGENTS_DIRNAME = './agents';
|
|
1219
1242
|
// <- TODO: [🕝] Make also `AGENTS_DIRNAME_ALTERNATIVES`
|
|
1220
|
-
// TODO: Just `.promptbook` in config, hardcode subfolders like `download-cache` or `execution-cache`
|
|
1221
1243
|
/**
|
|
1222
1244
|
* Where to store the temporary downloads
|
|
1223
1245
|
*
|
|
@@ -1225,7 +1247,7 @@ const DEFAULT_AGENTS_DIRNAME = './agents';
|
|
|
1225
1247
|
*
|
|
1226
1248
|
* @public exported from `@promptbook/core`
|
|
1227
1249
|
*/
|
|
1228
|
-
const DEFAULT_DOWNLOAD_CACHE_DIRNAME = '
|
|
1250
|
+
const DEFAULT_DOWNLOAD_CACHE_DIRNAME = getPromptbookTempPath('download-cache');
|
|
1229
1251
|
/**
|
|
1230
1252
|
* Where to store the cache of executions for promptbook CLI
|
|
1231
1253
|
*
|
|
@@ -1233,7 +1255,7 @@ const DEFAULT_DOWNLOAD_CACHE_DIRNAME = './.promptbook/download-cache';
|
|
|
1233
1255
|
*
|
|
1234
1256
|
* @public exported from `@promptbook/core`
|
|
1235
1257
|
*/
|
|
1236
|
-
const DEFAULT_EXECUTION_CACHE_DIRNAME = '
|
|
1258
|
+
const DEFAULT_EXECUTION_CACHE_DIRNAME = getPromptbookTempPath('execution-cache');
|
|
1237
1259
|
/**
|
|
1238
1260
|
* Where to store the scrape cache
|
|
1239
1261
|
*
|
|
@@ -1241,7 +1263,7 @@ const DEFAULT_EXECUTION_CACHE_DIRNAME = './.promptbook/execution-cache';
|
|
|
1241
1263
|
*
|
|
1242
1264
|
* @public exported from `@promptbook/core`
|
|
1243
1265
|
*/
|
|
1244
|
-
const DEFAULT_SCRAPE_CACHE_DIRNAME = '
|
|
1266
|
+
const DEFAULT_SCRAPE_CACHE_DIRNAME = getPromptbookTempPath('scrape-cache');
|
|
1245
1267
|
/**
|
|
1246
1268
|
* Id of application for the CLI when using remote server
|
|
1247
1269
|
*
|
|
@@ -14857,6 +14879,177 @@ function drawFractalCore(context, size, palette, timeMs, corePhase) {
|
|
|
14857
14879
|
context.restore();
|
|
14858
14880
|
}
|
|
14859
14881
|
|
|
14882
|
+
/* eslint-disable no-magic-numbers */
|
|
14883
|
+
/**
|
|
14884
|
+
* Builds the seeded six-face texture pack used by the Minecraft-style head cuboid.
|
|
14885
|
+
*
|
|
14886
|
+
* @param random Seeded random generator.
|
|
14887
|
+
* @param palette Derived avatar palette.
|
|
14888
|
+
* @param hasHeadband Whether the generated avatar should include a colored headband.
|
|
14889
|
+
* @returns Head cuboid textures.
|
|
14890
|
+
*
|
|
14891
|
+
* @private helper of the Minecraft avatar visuals
|
|
14892
|
+
*/
|
|
14893
|
+
function createMinecraftHeadTextures(random, palette, hasHeadband) {
|
|
14894
|
+
const faceTexture = createMinecraftFaceTexture(random, palette, hasHeadband);
|
|
14895
|
+
const hairColor = random() < 0.5 ? palette.primary : palette.secondary;
|
|
14896
|
+
const skinColor = palette.highlight;
|
|
14897
|
+
const headbandColor = hasHeadband ? palette.accent : hairColor;
|
|
14898
|
+
const sideTexture = createFilledTexture(skinColor);
|
|
14899
|
+
const backTexture = createFilledTexture(skinColor);
|
|
14900
|
+
const topTexture = createFilledTexture(hairColor);
|
|
14901
|
+
const bottomTexture = createFilledTexture(`${palette.shadow}cc`);
|
|
14902
|
+
fillTextureRect(sideTexture, 0, 0, 8, 3, hairColor);
|
|
14903
|
+
fillTextureRect(backTexture, 0, 0, 8, 5, hairColor);
|
|
14904
|
+
fillTextureRect(backTexture, 1, 5, 6, 1, hairColor);
|
|
14905
|
+
if (hasHeadband) {
|
|
14906
|
+
fillTextureRect(sideTexture, 0, 2, 8, 1, headbandColor);
|
|
14907
|
+
fillTextureRect(backTexture, 0, 2, 8, 1, headbandColor);
|
|
14908
|
+
fillTextureRect(topTexture, 0, 4, 8, 1, headbandColor);
|
|
14909
|
+
}
|
|
14910
|
+
sideTexture[4][4] = `${palette.shadow}99`;
|
|
14911
|
+
sideTexture[5][4] = `${palette.shadow}cc`;
|
|
14912
|
+
backTexture[6][2] = `${palette.shadow}99`;
|
|
14913
|
+
backTexture[6][5] = `${palette.shadow}99`;
|
|
14914
|
+
return {
|
|
14915
|
+
front: faceTexture,
|
|
14916
|
+
back: backTexture,
|
|
14917
|
+
left: sideTexture,
|
|
14918
|
+
right: mirrorMinecraftTexture(sideTexture),
|
|
14919
|
+
top: topTexture,
|
|
14920
|
+
bottom: bottomTexture,
|
|
14921
|
+
};
|
|
14922
|
+
}
|
|
14923
|
+
/**
|
|
14924
|
+
* Builds the seeded six-face texture pack used by the Minecraft-style torso cuboid.
|
|
14925
|
+
*
|
|
14926
|
+
* @param random Seeded random generator.
|
|
14927
|
+
* @param palette Derived avatar palette.
|
|
14928
|
+
* @returns Torso cuboid textures.
|
|
14929
|
+
*
|
|
14930
|
+
* @private helper of the Minecraft avatar visuals
|
|
14931
|
+
*/
|
|
14932
|
+
function createMinecraftTorsoTextures(random, palette) {
|
|
14933
|
+
const frontTexture = createMinecraftShirtTexture(random, palette);
|
|
14934
|
+
const sideTexture = createFilledTexture(palette.primary);
|
|
14935
|
+
const backTexture = createFilledTexture(palette.primary);
|
|
14936
|
+
const topTexture = createFilledTexture(`${palette.highlight}dd`);
|
|
14937
|
+
const bottomTexture = createFilledTexture(`${palette.shadow}dd`);
|
|
14938
|
+
const stripeColor = random() < 0.5 ? palette.secondary : palette.highlight;
|
|
14939
|
+
fillTextureRect(sideTexture, 0, 0, 8, 2, palette.shadow);
|
|
14940
|
+
fillTextureRect(backTexture, 0, 0, 8, 2, palette.shadow);
|
|
14941
|
+
fillTextureRect(backTexture, 3, 2, 2, 6, stripeColor);
|
|
14942
|
+
fillTextureRect(sideTexture, 4, 2, 1, 6, stripeColor);
|
|
14943
|
+
fillTextureRect(topTexture, 0, 0, 8, 2, palette.shadow);
|
|
14944
|
+
fillTextureRect(topTexture, 2, 2, 4, 4, stripeColor);
|
|
14945
|
+
return {
|
|
14946
|
+
front: frontTexture,
|
|
14947
|
+
back: backTexture,
|
|
14948
|
+
left: sideTexture,
|
|
14949
|
+
right: mirrorMinecraftTexture(sideTexture),
|
|
14950
|
+
top: topTexture,
|
|
14951
|
+
bottom: bottomTexture,
|
|
14952
|
+
};
|
|
14953
|
+
}
|
|
14954
|
+
/**
|
|
14955
|
+
* Mirrors one Minecraft texture horizontally.
|
|
14956
|
+
*
|
|
14957
|
+
* @param texture Source texture.
|
|
14958
|
+
* @returns Mirrored texture copy.
|
|
14959
|
+
*
|
|
14960
|
+
* @private helper of the Minecraft avatar visuals
|
|
14961
|
+
*/
|
|
14962
|
+
function mirrorMinecraftTexture(texture) {
|
|
14963
|
+
return texture.map((row) => [...row].reverse());
|
|
14964
|
+
}
|
|
14965
|
+
/**
|
|
14966
|
+
* Creates the front-face pixel texture for the cube head.
|
|
14967
|
+
*
|
|
14968
|
+
* @param random Seeded random generator.
|
|
14969
|
+
* @param palette Derived avatar palette.
|
|
14970
|
+
* @param hasHeadband Whether the avatar should render a headband row.
|
|
14971
|
+
* @returns 8x8 pixel texture.
|
|
14972
|
+
*
|
|
14973
|
+
* @private helper of the Minecraft avatar visuals
|
|
14974
|
+
*/
|
|
14975
|
+
function createMinecraftFaceTexture(random, palette, hasHeadband) {
|
|
14976
|
+
const texture = createFilledTexture(palette.highlight);
|
|
14977
|
+
const hairlineColor = random() < 0.5 ? palette.primary : palette.secondary;
|
|
14978
|
+
const cheekColor = random() < 0.5 ? `${palette.accent}bb` : `${palette.secondary}bb`;
|
|
14979
|
+
fillTextureRect(texture, 0, 0, 8, 2, hairlineColor);
|
|
14980
|
+
texture[2][0] = hairlineColor;
|
|
14981
|
+
texture[2][7] = hairlineColor;
|
|
14982
|
+
texture[3][0] = hairlineColor;
|
|
14983
|
+
texture[3][7] = hairlineColor;
|
|
14984
|
+
if (hasHeadband) {
|
|
14985
|
+
fillTextureRect(texture, 0, 2, 8, 1, palette.accent);
|
|
14986
|
+
}
|
|
14987
|
+
texture[3][2] = palette.ink;
|
|
14988
|
+
texture[3][5] = palette.ink;
|
|
14989
|
+
texture[4][2] = '#ffffff';
|
|
14990
|
+
texture[4][5] = '#ffffff';
|
|
14991
|
+
texture[5][1] = cheekColor;
|
|
14992
|
+
texture[5][6] = cheekColor;
|
|
14993
|
+
texture[5][3] = palette.shadow;
|
|
14994
|
+
texture[5][4] = palette.shadow;
|
|
14995
|
+
texture[6][3] = palette.shadow;
|
|
14996
|
+
texture[6][4] = palette.shadow;
|
|
14997
|
+
return texture;
|
|
14998
|
+
}
|
|
14999
|
+
/**
|
|
15000
|
+
* Creates the front-face pixel texture for the torso.
|
|
15001
|
+
*
|
|
15002
|
+
* @param random Seeded random generator.
|
|
15003
|
+
* @param palette Derived avatar palette.
|
|
15004
|
+
* @returns 8x8 torso texture.
|
|
15005
|
+
*
|
|
15006
|
+
* @private helper of the Minecraft avatar visuals
|
|
15007
|
+
*/
|
|
15008
|
+
function createMinecraftShirtTexture(random, palette) {
|
|
15009
|
+
const texture = createFilledTexture(palette.primary);
|
|
15010
|
+
const stripeColor = random() < 0.5 ? palette.secondary : palette.highlight;
|
|
15011
|
+
fillTextureRect(texture, 0, 0, 8, 2, palette.shadow);
|
|
15012
|
+
for (let rowIndex = 2; rowIndex < 8; rowIndex++) {
|
|
15013
|
+
texture[rowIndex][3] = stripeColor;
|
|
15014
|
+
texture[rowIndex][4] = stripeColor;
|
|
15015
|
+
}
|
|
15016
|
+
texture[4][1] = palette.accent;
|
|
15017
|
+
texture[4][6] = palette.accent;
|
|
15018
|
+
texture[5][2] = palette.highlight;
|
|
15019
|
+
texture[5][5] = palette.highlight;
|
|
15020
|
+
return texture;
|
|
15021
|
+
}
|
|
15022
|
+
/**
|
|
15023
|
+
* Creates one solid-color 8x8 Minecraft texture.
|
|
15024
|
+
*
|
|
15025
|
+
* @param color Fill color.
|
|
15026
|
+
* @returns Filled 8x8 texture.
|
|
15027
|
+
*
|
|
15028
|
+
* @private helper of the Minecraft avatar visuals
|
|
15029
|
+
*/
|
|
15030
|
+
function createFilledTexture(color) {
|
|
15031
|
+
return Array.from({ length: 8 }, () => Array.from({ length: 8 }, () => color));
|
|
15032
|
+
}
|
|
15033
|
+
/**
|
|
15034
|
+
* Fills one rectangular area inside a mutable Minecraft texture.
|
|
15035
|
+
*
|
|
15036
|
+
* @param texture Mutable target texture.
|
|
15037
|
+
* @param x Left texture coordinate.
|
|
15038
|
+
* @param y Top texture coordinate.
|
|
15039
|
+
* @param width Rectangle width.
|
|
15040
|
+
* @param height Rectangle height.
|
|
15041
|
+
* @param color Fill color.
|
|
15042
|
+
*
|
|
15043
|
+
* @private helper of the Minecraft avatar visuals
|
|
15044
|
+
*/
|
|
15045
|
+
function fillTextureRect(texture, x, y, width, height, color) {
|
|
15046
|
+
for (let rowIndex = y; rowIndex < y + height; rowIndex++) {
|
|
15047
|
+
for (let columnIndex = x; columnIndex < x + width; columnIndex++) {
|
|
15048
|
+
texture[rowIndex][columnIndex] = color;
|
|
15049
|
+
}
|
|
15050
|
+
}
|
|
15051
|
+
}
|
|
15052
|
+
|
|
14860
15053
|
/* eslint-disable no-magic-numbers */
|
|
14861
15054
|
/**
|
|
14862
15055
|
* Minecraft-style 3D avatar visual.
|
|
@@ -14881,8 +15074,8 @@ const minecraftAvatarVisual = {
|
|
|
14881
15074
|
const bodyX = size * 0.33;
|
|
14882
15075
|
const bodyY = headY + headSize * 0.96;
|
|
14883
15076
|
const hasHeadband = random() < 0.5;
|
|
14884
|
-
const
|
|
14885
|
-
const
|
|
15077
|
+
const headTextures = createMinecraftHeadTextures(createRandom('minecraft-face'), palette, hasHeadband);
|
|
15078
|
+
const torsoTextures = createMinecraftTorsoTextures(createRandom('minecraft-shirt'), palette);
|
|
14886
15079
|
drawAvatarFrame(context, size, palette);
|
|
14887
15080
|
const spotlight = context.createRadialGradient(size * 0.5, size * 0.18, size * 0.05, size * 0.5, size * 0.18, size * 0.5);
|
|
14888
15081
|
spotlight.addColorStop(0, `${palette.highlight}66`);
|
|
@@ -14902,7 +15095,7 @@ const minecraftAvatarVisual = {
|
|
|
14902
15095
|
width: bodyWidth,
|
|
14903
15096
|
height: bodyHeight,
|
|
14904
15097
|
depth: bodyDepth,
|
|
14905
|
-
frontTexture:
|
|
15098
|
+
frontTexture: torsoTextures.front,
|
|
14906
15099
|
topColor: `${palette.highlight}cc`,
|
|
14907
15100
|
sideColor: `${palette.secondary}dd`,
|
|
14908
15101
|
outlineColor: `${palette.shadow}aa`,
|
|
@@ -14913,7 +15106,7 @@ const minecraftAvatarVisual = {
|
|
|
14913
15106
|
width: headSize,
|
|
14914
15107
|
height: headSize,
|
|
14915
15108
|
depth,
|
|
14916
|
-
frontTexture:
|
|
15109
|
+
frontTexture: headTextures.front,
|
|
14917
15110
|
topColor: `${palette.highlight}ee`,
|
|
14918
15111
|
sideColor: `${palette.secondary}ee`,
|
|
14919
15112
|
outlineColor: `${palette.shadow}cc`,
|
|
@@ -14978,72 +15171,505 @@ function drawVoxelCuboid(context, cuboid) {
|
|
|
14978
15171
|
context.closePath();
|
|
14979
15172
|
context.stroke();
|
|
14980
15173
|
}
|
|
15174
|
+
|
|
15175
|
+
/* eslint-disable no-magic-numbers */
|
|
14981
15176
|
/**
|
|
14982
|
-
*
|
|
15177
|
+
* Fixed scene camera distance used for the proper-3D projection.
|
|
14983
15178
|
*
|
|
14984
|
-
* @
|
|
15179
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
15180
|
+
*/
|
|
15181
|
+
const CAMERA_DISTANCE_RATIO = 1.4;
|
|
15182
|
+
/**
|
|
15183
|
+
* Shared light direction used to shade projected cuboid faces.
|
|
15184
|
+
*
|
|
15185
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
15186
|
+
*/
|
|
15187
|
+
const LIGHT_DIRECTION = normalizeVector3({
|
|
15188
|
+
x: 0.4,
|
|
15189
|
+
y: -0.65,
|
|
15190
|
+
z: 0.92,
|
|
15191
|
+
});
|
|
15192
|
+
/**
|
|
15193
|
+
* Minecraft 3D 2 avatar visual.
|
|
15194
|
+
*
|
|
15195
|
+
* @private built-in avatar visual
|
|
15196
|
+
*/
|
|
15197
|
+
const minecraft2AvatarVisual = {
|
|
15198
|
+
id: 'minecraft2',
|
|
15199
|
+
title: 'Minecraft 3D 2',
|
|
15200
|
+
description: 'Proper 3D Minecraft-style portrait with textured cuboids and pointer-driven head turns.',
|
|
15201
|
+
isAnimated: true,
|
|
15202
|
+
supportsPointerTracking: true,
|
|
15203
|
+
render({ context, size, palette, createRandom, timeMs, interaction }) {
|
|
15204
|
+
const spotlightY = size * 0.22;
|
|
15205
|
+
const headRandom = createRandom('minecraft2-head');
|
|
15206
|
+
const hasHeadband = headRandom() < 0.5;
|
|
15207
|
+
const headTextures = createMinecraftHeadTextures(createRandom('minecraft2-head-textures'), palette, hasHeadband);
|
|
15208
|
+
const torsoTextures = createMinecraftTorsoTextures(createRandom('minecraft2-body-textures'), palette);
|
|
15209
|
+
const bob = Math.sin(timeMs / 880) * size * 0.014;
|
|
15210
|
+
const bodyYaw = -0.24 + Math.sin(timeMs / 2300) * 0.06 + interaction.bodyOffsetX * 0.16;
|
|
15211
|
+
const bodyPitch = -0.12 + Math.cos(timeMs / 2800) * 0.02 - interaction.bodyOffsetY * 0.06;
|
|
15212
|
+
const headYaw = -0.18 + Math.sin(timeMs / 1900 + 0.6) * 0.05 + interaction.gazeX * 0.62;
|
|
15213
|
+
const headPitch = -0.12 + Math.cos(timeMs / 2400 + 1.1) * 0.03 - interaction.gazeY * 0.38;
|
|
15214
|
+
const sceneCenterX = size * 0.5;
|
|
15215
|
+
const sceneCenterY = size * 0.57;
|
|
15216
|
+
const bodyWidth = size * 0.225;
|
|
15217
|
+
const bodyHeight = size * 0.245;
|
|
15218
|
+
const bodyDepth = size * 0.145;
|
|
15219
|
+
const headSize = size * 0.24;
|
|
15220
|
+
const headLift = size * 0.205;
|
|
15221
|
+
const headForwardShift = interaction.intensity * size * 0.018;
|
|
15222
|
+
const sceneCuboids = [
|
|
15223
|
+
{
|
|
15224
|
+
center: {
|
|
15225
|
+
x: interaction.bodyOffsetX * size * 0.026,
|
|
15226
|
+
y: size * 0.05 + interaction.bodyOffsetY * size * 0.018 + bob,
|
|
15227
|
+
z: 0,
|
|
15228
|
+
},
|
|
15229
|
+
width: bodyWidth,
|
|
15230
|
+
height: bodyHeight,
|
|
15231
|
+
depth: bodyDepth,
|
|
15232
|
+
rotationX: bodyPitch,
|
|
15233
|
+
rotationY: bodyYaw,
|
|
15234
|
+
textures: torsoTextures,
|
|
15235
|
+
outlineColor: `${palette.shadow}cc`,
|
|
15236
|
+
},
|
|
15237
|
+
{
|
|
15238
|
+
center: {
|
|
15239
|
+
x: interaction.bodyOffsetX * size * 0.018 + interaction.gazeX * size * 0.016,
|
|
15240
|
+
y: -headLift + bob * 1.15,
|
|
15241
|
+
z: headForwardShift,
|
|
15242
|
+
},
|
|
15243
|
+
width: headSize,
|
|
15244
|
+
height: headSize,
|
|
15245
|
+
depth: headSize,
|
|
15246
|
+
rotationX: headPitch,
|
|
15247
|
+
rotationY: headYaw,
|
|
15248
|
+
textures: headTextures,
|
|
15249
|
+
outlineColor: `${palette.shadow}dd`,
|
|
15250
|
+
},
|
|
15251
|
+
];
|
|
15252
|
+
const visibleFaces = sceneCuboids
|
|
15253
|
+
.flatMap((cuboid) => resolveVisibleCuboidFaces(cuboid, size, sceneCenterX, sceneCenterY))
|
|
15254
|
+
.sort((firstFace, secondFace) => firstFace.averageDepth - secondFace.averageDepth);
|
|
15255
|
+
drawAvatarFrame(context, size, palette);
|
|
15256
|
+
drawMinecraftBackdrop(context, size, palette, sceneCenterX, spotlightY, interaction, timeMs);
|
|
15257
|
+
drawMinecraftShadow(context, size, palette, interaction, timeMs);
|
|
15258
|
+
for (const visibleFace of visibleFaces) {
|
|
15259
|
+
drawTexturedProjectedFace(context, visibleFace);
|
|
15260
|
+
}
|
|
15261
|
+
},
|
|
15262
|
+
};
|
|
15263
|
+
/**
|
|
15264
|
+
* Draws the shared background atmosphere behind the Minecraft 3D 2 portrait.
|
|
15265
|
+
*
|
|
15266
|
+
* @param context Canvas 2D context.
|
|
15267
|
+
* @param size Canvas size in CSS pixels.
|
|
14985
15268
|
* @param palette Derived avatar palette.
|
|
14986
|
-
* @param
|
|
14987
|
-
* @
|
|
15269
|
+
* @param sceneCenterX Horizontal scene center.
|
|
15270
|
+
* @param spotlightY Vertical spotlight anchor.
|
|
15271
|
+
* @param interaction Smoothed pointer-aware interaction state.
|
|
15272
|
+
* @param timeMs Current animation time in milliseconds.
|
|
14988
15273
|
*
|
|
14989
|
-
* @private helper of `
|
|
15274
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
14990
15275
|
*/
|
|
14991
|
-
function
|
|
14992
|
-
const
|
|
14993
|
-
|
|
14994
|
-
|
|
14995
|
-
|
|
14996
|
-
|
|
14997
|
-
|
|
15276
|
+
function drawMinecraftBackdrop(context, size, palette, sceneCenterX, spotlightY, interaction, timeMs) {
|
|
15277
|
+
const spotlightGradient = context.createRadialGradient(sceneCenterX + interaction.gazeX * size * 0.08, spotlightY + interaction.gazeY * size * 0.05, size * 0.03, sceneCenterX, spotlightY, size * 0.52);
|
|
15278
|
+
spotlightGradient.addColorStop(0, `${palette.highlight}66`);
|
|
15279
|
+
spotlightGradient.addColorStop(0.42, `${palette.accent}1d`);
|
|
15280
|
+
spotlightGradient.addColorStop(1, `${palette.highlight}00`);
|
|
15281
|
+
context.fillStyle = spotlightGradient;
|
|
15282
|
+
context.fillRect(0, 0, size, size);
|
|
15283
|
+
const rimGradient = context.createLinearGradient(0, size * 0.14, 0, size * 0.92);
|
|
15284
|
+
rimGradient.addColorStop(0, `${palette.highlight}12`);
|
|
15285
|
+
rimGradient.addColorStop(0.55, `${palette.secondary}0a`);
|
|
15286
|
+
rimGradient.addColorStop(1, `${palette.shadow}00`);
|
|
15287
|
+
context.fillStyle = rimGradient;
|
|
15288
|
+
context.fillRect(0, 0, size, size);
|
|
15289
|
+
context.save();
|
|
15290
|
+
context.globalAlpha = 0.08 + interaction.intensity * 0.04;
|
|
15291
|
+
context.fillStyle = palette.highlight;
|
|
15292
|
+
context.beginPath();
|
|
15293
|
+
context.arc(size * 0.72 + Math.sin(timeMs / 1600) * size * 0.03, size * 0.2 + Math.cos(timeMs / 1400) * size * 0.018, size * 0.025, 0, Math.PI * 2);
|
|
15294
|
+
context.fill();
|
|
15295
|
+
context.restore();
|
|
15296
|
+
}
|
|
15297
|
+
/**
|
|
15298
|
+
* Draws the soft floor shadow used to anchor the cuboids in the frame.
|
|
15299
|
+
*
|
|
15300
|
+
* @param context Canvas 2D context.
|
|
15301
|
+
* @param size Canvas size in CSS pixels.
|
|
15302
|
+
* @param palette Derived avatar palette.
|
|
15303
|
+
* @param interaction Smoothed pointer-aware interaction state.
|
|
15304
|
+
* @param timeMs Current animation time in milliseconds.
|
|
15305
|
+
*
|
|
15306
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
15307
|
+
*/
|
|
15308
|
+
function drawMinecraftShadow(context, size, palette, interaction, timeMs) {
|
|
15309
|
+
context.save();
|
|
15310
|
+
context.fillStyle = `${palette.shadow}66`;
|
|
15311
|
+
context.filter = `blur(${size * 0.02}px)`;
|
|
15312
|
+
context.beginPath();
|
|
15313
|
+
context.ellipse(size * 0.5 + interaction.gazeX * size * 0.03, size * 0.85 + Math.sin(timeMs / 880) * size * 0.01, size * (0.16 + interaction.intensity * 0.015), size * 0.055, 0, 0, Math.PI * 2);
|
|
15314
|
+
context.fill();
|
|
15315
|
+
context.restore();
|
|
15316
|
+
}
|
|
15317
|
+
/**
|
|
15318
|
+
* Resolves all visible projected faces for one scene cuboid.
|
|
15319
|
+
*
|
|
15320
|
+
* @param cuboid Scene cuboid definition.
|
|
15321
|
+
* @param size Canvas size in CSS pixels.
|
|
15322
|
+
* @param sceneCenterX Horizontal scene center.
|
|
15323
|
+
* @param sceneCenterY Vertical scene center.
|
|
15324
|
+
* @returns Visible faces sorted later by depth.
|
|
15325
|
+
*
|
|
15326
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
15327
|
+
*/
|
|
15328
|
+
function resolveVisibleCuboidFaces(cuboid, size, sceneCenterX, sceneCenterY) {
|
|
15329
|
+
const halfWidth = cuboid.width / 2;
|
|
15330
|
+
const halfHeight = cuboid.height / 2;
|
|
15331
|
+
const halfDepth = cuboid.depth / 2;
|
|
15332
|
+
const faceDefinitions = [
|
|
15333
|
+
{
|
|
15334
|
+
texture: cuboid.textures.front,
|
|
15335
|
+
corners: [
|
|
15336
|
+
{ x: -halfWidth, y: -halfHeight, z: halfDepth },
|
|
15337
|
+
{ x: halfWidth, y: -halfHeight, z: halfDepth },
|
|
15338
|
+
{ x: halfWidth, y: halfHeight, z: halfDepth },
|
|
15339
|
+
{ x: -halfWidth, y: halfHeight, z: halfDepth },
|
|
15340
|
+
],
|
|
15341
|
+
},
|
|
15342
|
+
{
|
|
15343
|
+
texture: cuboid.textures.back,
|
|
15344
|
+
corners: [
|
|
15345
|
+
{ x: halfWidth, y: -halfHeight, z: -halfDepth },
|
|
15346
|
+
{ x: -halfWidth, y: -halfHeight, z: -halfDepth },
|
|
15347
|
+
{ x: -halfWidth, y: halfHeight, z: -halfDepth },
|
|
15348
|
+
{ x: halfWidth, y: halfHeight, z: -halfDepth },
|
|
15349
|
+
],
|
|
15350
|
+
},
|
|
15351
|
+
{
|
|
15352
|
+
texture: cuboid.textures.right,
|
|
15353
|
+
corners: [
|
|
15354
|
+
{ x: halfWidth, y: -halfHeight, z: halfDepth },
|
|
15355
|
+
{ x: halfWidth, y: -halfHeight, z: -halfDepth },
|
|
15356
|
+
{ x: halfWidth, y: halfHeight, z: -halfDepth },
|
|
15357
|
+
{ x: halfWidth, y: halfHeight, z: halfDepth },
|
|
15358
|
+
],
|
|
15359
|
+
},
|
|
15360
|
+
{
|
|
15361
|
+
texture: cuboid.textures.left,
|
|
15362
|
+
corners: [
|
|
15363
|
+
{ x: -halfWidth, y: -halfHeight, z: -halfDepth },
|
|
15364
|
+
{ x: -halfWidth, y: -halfHeight, z: halfDepth },
|
|
15365
|
+
{ x: -halfWidth, y: halfHeight, z: halfDepth },
|
|
15366
|
+
{ x: -halfWidth, y: halfHeight, z: -halfDepth },
|
|
15367
|
+
],
|
|
15368
|
+
},
|
|
15369
|
+
{
|
|
15370
|
+
texture: cuboid.textures.top,
|
|
15371
|
+
corners: [
|
|
15372
|
+
{ x: -halfWidth, y: -halfHeight, z: -halfDepth },
|
|
15373
|
+
{ x: halfWidth, y: -halfHeight, z: -halfDepth },
|
|
15374
|
+
{ x: halfWidth, y: -halfHeight, z: halfDepth },
|
|
15375
|
+
{ x: -halfWidth, y: -halfHeight, z: halfDepth },
|
|
15376
|
+
],
|
|
15377
|
+
},
|
|
15378
|
+
{
|
|
15379
|
+
texture: cuboid.textures.bottom,
|
|
15380
|
+
corners: [
|
|
15381
|
+
{ x: -halfWidth, y: halfHeight, z: halfDepth },
|
|
15382
|
+
{ x: halfWidth, y: halfHeight, z: halfDepth },
|
|
15383
|
+
{ x: halfWidth, y: halfHeight, z: -halfDepth },
|
|
15384
|
+
{ x: -halfWidth, y: halfHeight, z: -halfDepth },
|
|
15385
|
+
],
|
|
15386
|
+
},
|
|
15387
|
+
];
|
|
15388
|
+
const visibleFaces = faceDefinitions
|
|
15389
|
+
.map((faceDefinition) => {
|
|
15390
|
+
const transformedCorners = faceDefinition.corners.map((corner) => transformScenePoint(corner, cuboid.center, cuboid.rotationX, cuboid.rotationY));
|
|
15391
|
+
const faceNormal = normalizeVector3(crossProduct3D(subtractPoint3D(transformedCorners[1], transformedCorners[0]), subtractPoint3D(transformedCorners[2], transformedCorners[0])));
|
|
15392
|
+
if (faceNormal.z <= 0.02) {
|
|
15393
|
+
return null;
|
|
14998
15394
|
}
|
|
15395
|
+
const projectedCorners = transformedCorners.map((corner) => projectScenePoint(corner, size, sceneCenterX, sceneCenterY));
|
|
15396
|
+
return {
|
|
15397
|
+
corners: projectedCorners,
|
|
15398
|
+
texture: faceDefinition.texture,
|
|
15399
|
+
averageDepth: transformedCorners.reduce((depthSum, corner) => depthSum + corner.z, 0) / transformedCorners.length,
|
|
15400
|
+
lightIntensity: clampNumber$1(dotProduct3D(faceNormal, LIGHT_DIRECTION), -1, 1),
|
|
15401
|
+
outlineColor: cuboid.outlineColor,
|
|
15402
|
+
};
|
|
15403
|
+
});
|
|
15404
|
+
return visibleFaces.filter((visibleFace) => visibleFace !== null);
|
|
15405
|
+
}
|
|
15406
|
+
/**
|
|
15407
|
+
* Draws one projected textured face by tessellating its texture cells into quads.
|
|
15408
|
+
*
|
|
15409
|
+
* @param context Canvas 2D context.
|
|
15410
|
+
* @param face Visible projected face.
|
|
15411
|
+
*
|
|
15412
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
15413
|
+
*/
|
|
15414
|
+
function drawTexturedProjectedFace(context, face) {
|
|
15415
|
+
var _a;
|
|
15416
|
+
const rows = face.texture.length;
|
|
15417
|
+
const columns = ((_a = face.texture[0]) === null || _a === void 0 ? void 0 : _a.length) || 0;
|
|
15418
|
+
if (rows === 0 || columns === 0) {
|
|
15419
|
+
return;
|
|
14999
15420
|
}
|
|
15000
|
-
|
|
15001
|
-
|
|
15002
|
-
|
|
15003
|
-
|
|
15004
|
-
|
|
15005
|
-
|
|
15006
|
-
|
|
15421
|
+
for (let rowIndex = 0; rowIndex < rows; rowIndex++) {
|
|
15422
|
+
for (let columnIndex = 0; columnIndex < columns; columnIndex++) {
|
|
15423
|
+
const startX = columnIndex / columns;
|
|
15424
|
+
const endX = (columnIndex + 1) / columns;
|
|
15425
|
+
const startY = rowIndex / rows;
|
|
15426
|
+
const endY = (rowIndex + 1) / rows;
|
|
15427
|
+
drawProjectedQuad(context, [
|
|
15428
|
+
interpolateProjectedQuad(face.corners, startX, startY),
|
|
15429
|
+
interpolateProjectedQuad(face.corners, endX, startY),
|
|
15430
|
+
interpolateProjectedQuad(face.corners, endX, endY),
|
|
15431
|
+
interpolateProjectedQuad(face.corners, startX, endY),
|
|
15432
|
+
], face.texture[rowIndex][columnIndex]);
|
|
15007
15433
|
}
|
|
15008
15434
|
}
|
|
15009
|
-
|
|
15010
|
-
|
|
15011
|
-
|
|
15012
|
-
|
|
15013
|
-
|
|
15014
|
-
|
|
15015
|
-
|
|
15016
|
-
|
|
15017
|
-
|
|
15018
|
-
|
|
15019
|
-
|
|
15435
|
+
if (face.lightIntensity > 0) {
|
|
15436
|
+
drawProjectedQuad(context, face.corners, `rgba(255, 255, 255, ${0.15 * face.lightIntensity})`);
|
|
15437
|
+
}
|
|
15438
|
+
else if (face.lightIntensity < 0) {
|
|
15439
|
+
drawProjectedQuad(context, face.corners, `rgba(0, 0, 0, ${0.22 * Math.abs(face.lightIntensity)})`);
|
|
15440
|
+
}
|
|
15441
|
+
context.save();
|
|
15442
|
+
context.beginPath();
|
|
15443
|
+
context.moveTo(face.corners[0].x, face.corners[0].y);
|
|
15444
|
+
for (let cornerIndex = 1; cornerIndex < face.corners.length; cornerIndex++) {
|
|
15445
|
+
context.lineTo(face.corners[cornerIndex].x, face.corners[cornerIndex].y);
|
|
15446
|
+
}
|
|
15447
|
+
context.closePath();
|
|
15448
|
+
context.strokeStyle = face.outlineColor;
|
|
15449
|
+
context.lineWidth = Math.max(1.1, getProjectedQuadPerimeter(face.corners) * 0.0045);
|
|
15450
|
+
context.lineJoin = 'round';
|
|
15451
|
+
context.stroke();
|
|
15452
|
+
context.restore();
|
|
15020
15453
|
}
|
|
15021
15454
|
/**
|
|
15022
|
-
*
|
|
15455
|
+
* Draws one filled projected quad.
|
|
15023
15456
|
*
|
|
15024
|
-
* @param
|
|
15025
|
-
* @param
|
|
15026
|
-
* @
|
|
15457
|
+
* @param context Canvas 2D context.
|
|
15458
|
+
* @param corners Quad corners in clockwise order.
|
|
15459
|
+
* @param fillStyle CSS fill style.
|
|
15027
15460
|
*
|
|
15028
|
-
* @private helper of `
|
|
15461
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
15029
15462
|
*/
|
|
15030
|
-
function
|
|
15031
|
-
|
|
15032
|
-
|
|
15033
|
-
|
|
15034
|
-
|
|
15035
|
-
|
|
15036
|
-
|
|
15463
|
+
function drawProjectedQuad(context, corners, fillStyle) {
|
|
15464
|
+
context.beginPath();
|
|
15465
|
+
context.moveTo(corners[0].x, corners[0].y);
|
|
15466
|
+
context.lineTo(corners[1].x, corners[1].y);
|
|
15467
|
+
context.lineTo(corners[2].x, corners[2].y);
|
|
15468
|
+
context.lineTo(corners[3].x, corners[3].y);
|
|
15469
|
+
context.closePath();
|
|
15470
|
+
context.fillStyle = fillStyle;
|
|
15471
|
+
context.fill();
|
|
15472
|
+
}
|
|
15473
|
+
/**
|
|
15474
|
+
* Interpolates one point inside a projected quad across both quad axes.
|
|
15475
|
+
*
|
|
15476
|
+
* @param corners Quad corners in clockwise order.
|
|
15477
|
+
* @param horizontalRatio Horizontal ratio in the range `[0, 1]`.
|
|
15478
|
+
* @param verticalRatio Vertical ratio in the range `[0, 1]`.
|
|
15479
|
+
* @returns Interpolated projected point.
|
|
15480
|
+
*
|
|
15481
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
15482
|
+
*/
|
|
15483
|
+
function interpolateProjectedQuad(corners, horizontalRatio, verticalRatio) {
|
|
15484
|
+
const topPoint = interpolateProjectedPoint(corners[0], corners[1], horizontalRatio);
|
|
15485
|
+
const bottomPoint = interpolateProjectedPoint(corners[3], corners[2], horizontalRatio);
|
|
15486
|
+
return interpolateProjectedPoint(topPoint, bottomPoint, verticalRatio);
|
|
15487
|
+
}
|
|
15488
|
+
/**
|
|
15489
|
+
* Interpolates between two projected points.
|
|
15490
|
+
*
|
|
15491
|
+
* @param startPoint Start point.
|
|
15492
|
+
* @param endPoint End point.
|
|
15493
|
+
* @param ratio Interpolation ratio in the range `[0, 1]`.
|
|
15494
|
+
* @returns Interpolated projected point.
|
|
15495
|
+
*
|
|
15496
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
15497
|
+
*/
|
|
15498
|
+
function interpolateProjectedPoint(startPoint, endPoint, ratio) {
|
|
15499
|
+
return {
|
|
15500
|
+
x: startPoint.x + (endPoint.x - startPoint.x) * ratio,
|
|
15501
|
+
y: startPoint.y + (endPoint.y - startPoint.y) * ratio,
|
|
15502
|
+
z: startPoint.z + (endPoint.z - startPoint.z) * ratio,
|
|
15503
|
+
};
|
|
15504
|
+
}
|
|
15505
|
+
/**
|
|
15506
|
+
* Projects one rotated scene point into canvas coordinates.
|
|
15507
|
+
*
|
|
15508
|
+
* @param point Scene point.
|
|
15509
|
+
* @param size Canvas size in CSS pixels.
|
|
15510
|
+
* @param sceneCenterX Horizontal scene center.
|
|
15511
|
+
* @param sceneCenterY Vertical scene center.
|
|
15512
|
+
* @returns Projected point.
|
|
15513
|
+
*
|
|
15514
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
15515
|
+
*/
|
|
15516
|
+
function projectScenePoint(point, size, sceneCenterX, sceneCenterY) {
|
|
15517
|
+
const cameraDistance = size * CAMERA_DISTANCE_RATIO;
|
|
15518
|
+
const perspectiveScale = cameraDistance / Math.max(cameraDistance - point.z, cameraDistance * 0.35);
|
|
15519
|
+
return {
|
|
15520
|
+
x: sceneCenterX + point.x * perspectiveScale,
|
|
15521
|
+
y: sceneCenterY + point.y * perspectiveScale,
|
|
15522
|
+
z: point.z,
|
|
15523
|
+
};
|
|
15524
|
+
}
|
|
15525
|
+
/**
|
|
15526
|
+
* Applies the local cuboid rotations and translation to one scene point.
|
|
15527
|
+
*
|
|
15528
|
+
* @param localPoint Point in cuboid-local space.
|
|
15529
|
+
* @param center Cuboid center in scene space.
|
|
15530
|
+
* @param rotationX Cuboid pitch in radians.
|
|
15531
|
+
* @param rotationY Cuboid yaw in radians.
|
|
15532
|
+
* @returns Transformed scene-space point.
|
|
15533
|
+
*
|
|
15534
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
15535
|
+
*/
|
|
15536
|
+
function transformScenePoint(localPoint, center, rotationX, rotationY) {
|
|
15537
|
+
const yawedPoint = rotatePointAroundY(localPoint, rotationY);
|
|
15538
|
+
const pitchedPoint = rotatePointAroundX(yawedPoint, rotationX);
|
|
15539
|
+
return {
|
|
15540
|
+
x: center.x + pitchedPoint.x,
|
|
15541
|
+
y: center.y + pitchedPoint.y,
|
|
15542
|
+
z: center.z + pitchedPoint.z,
|
|
15543
|
+
};
|
|
15544
|
+
}
|
|
15545
|
+
/**
|
|
15546
|
+
* Rotates one point around the local Y axis.
|
|
15547
|
+
*
|
|
15548
|
+
* @param point Source point.
|
|
15549
|
+
* @param angle Rotation angle in radians.
|
|
15550
|
+
* @returns Rotated point.
|
|
15551
|
+
*
|
|
15552
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
15553
|
+
*/
|
|
15554
|
+
function rotatePointAroundY(point, angle) {
|
|
15555
|
+
const cosine = Math.cos(angle);
|
|
15556
|
+
const sine = Math.sin(angle);
|
|
15557
|
+
return {
|
|
15558
|
+
x: point.x * cosine + point.z * sine,
|
|
15559
|
+
y: point.y,
|
|
15560
|
+
z: -point.x * sine + point.z * cosine,
|
|
15561
|
+
};
|
|
15562
|
+
}
|
|
15563
|
+
/**
|
|
15564
|
+
* Rotates one point around the local X axis.
|
|
15565
|
+
*
|
|
15566
|
+
* @param point Source point.
|
|
15567
|
+
* @param angle Rotation angle in radians.
|
|
15568
|
+
* @returns Rotated point.
|
|
15569
|
+
*
|
|
15570
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
15571
|
+
*/
|
|
15572
|
+
function rotatePointAroundX(point, angle) {
|
|
15573
|
+
const cosine = Math.cos(angle);
|
|
15574
|
+
const sine = Math.sin(angle);
|
|
15575
|
+
return {
|
|
15576
|
+
x: point.x,
|
|
15577
|
+
y: point.y * cosine - point.z * sine,
|
|
15578
|
+
z: point.y * sine + point.z * cosine,
|
|
15579
|
+
};
|
|
15580
|
+
}
|
|
15581
|
+
/**
|
|
15582
|
+
* Subtracts one 3D point from another.
|
|
15583
|
+
*
|
|
15584
|
+
* @param leftPoint Left point.
|
|
15585
|
+
* @param rightPoint Right point.
|
|
15586
|
+
* @returns Difference vector.
|
|
15587
|
+
*
|
|
15588
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
15589
|
+
*/
|
|
15590
|
+
function subtractPoint3D(leftPoint, rightPoint) {
|
|
15591
|
+
return {
|
|
15592
|
+
x: leftPoint.x - rightPoint.x,
|
|
15593
|
+
y: leftPoint.y - rightPoint.y,
|
|
15594
|
+
z: leftPoint.z - rightPoint.z,
|
|
15595
|
+
};
|
|
15596
|
+
}
|
|
15597
|
+
/**
|
|
15598
|
+
* Computes the 3D cross product of two vectors.
|
|
15599
|
+
*
|
|
15600
|
+
* @param leftVector Left vector.
|
|
15601
|
+
* @param rightVector Right vector.
|
|
15602
|
+
* @returns Cross product.
|
|
15603
|
+
*
|
|
15604
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
15605
|
+
*/
|
|
15606
|
+
function crossProduct3D(leftVector, rightVector) {
|
|
15607
|
+
return {
|
|
15608
|
+
x: leftVector.y * rightVector.z - leftVector.z * rightVector.y,
|
|
15609
|
+
y: leftVector.z * rightVector.x - leftVector.x * rightVector.z,
|
|
15610
|
+
z: leftVector.x * rightVector.y - leftVector.y * rightVector.x,
|
|
15611
|
+
};
|
|
15612
|
+
}
|
|
15613
|
+
/**
|
|
15614
|
+
* Computes the 3D dot product of two vectors.
|
|
15615
|
+
*
|
|
15616
|
+
* @param leftVector Left vector.
|
|
15617
|
+
* @param rightVector Right vector.
|
|
15618
|
+
* @returns Dot product.
|
|
15619
|
+
*
|
|
15620
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
15621
|
+
*/
|
|
15622
|
+
function dotProduct3D(leftVector, rightVector) {
|
|
15623
|
+
return leftVector.x * rightVector.x + leftVector.y * rightVector.y + leftVector.z * rightVector.z;
|
|
15624
|
+
}
|
|
15625
|
+
/**
|
|
15626
|
+
* Normalizes one 3D vector while keeping zero vectors stable.
|
|
15627
|
+
*
|
|
15628
|
+
* @param vector Source vector.
|
|
15629
|
+
* @returns Normalized vector.
|
|
15630
|
+
*
|
|
15631
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
15632
|
+
*/
|
|
15633
|
+
function normalizeVector3(vector) {
|
|
15634
|
+
const length = Math.hypot(vector.x, vector.y, vector.z);
|
|
15635
|
+
if (length === 0) {
|
|
15636
|
+
return vector;
|
|
15037
15637
|
}
|
|
15038
|
-
|
|
15039
|
-
|
|
15040
|
-
|
|
15638
|
+
return {
|
|
15639
|
+
x: vector.x / length,
|
|
15640
|
+
y: vector.y / length,
|
|
15641
|
+
z: vector.z / length,
|
|
15642
|
+
};
|
|
15643
|
+
}
|
|
15644
|
+
/**
|
|
15645
|
+
* Clamps one number into the provided range.
|
|
15646
|
+
*
|
|
15647
|
+
* @param value Input value.
|
|
15648
|
+
* @param minimumValue Inclusive lower bound.
|
|
15649
|
+
* @param maximumValue Inclusive upper bound.
|
|
15650
|
+
* @returns Clamped value.
|
|
15651
|
+
*
|
|
15652
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
15653
|
+
*/
|
|
15654
|
+
function clampNumber$1(value, minimumValue, maximumValue) {
|
|
15655
|
+
return Math.min(maximumValue, Math.max(minimumValue, value));
|
|
15656
|
+
}
|
|
15657
|
+
/**
|
|
15658
|
+
* Measures the perimeter of one projected quad.
|
|
15659
|
+
*
|
|
15660
|
+
* @param corners Quad corners.
|
|
15661
|
+
* @returns Perimeter length.
|
|
15662
|
+
*
|
|
15663
|
+
* @private helper of `minecraft2AvatarVisual`
|
|
15664
|
+
*/
|
|
15665
|
+
function getProjectedQuadPerimeter(corners) {
|
|
15666
|
+
let perimeter = 0;
|
|
15667
|
+
for (let cornerIndex = 0; cornerIndex < corners.length; cornerIndex++) {
|
|
15668
|
+
const currentCorner = corners[cornerIndex];
|
|
15669
|
+
const nextCorner = corners[(cornerIndex + 1) % corners.length];
|
|
15670
|
+
perimeter += Math.hypot(nextCorner.x - currentCorner.x, nextCorner.y - currentCorner.y);
|
|
15041
15671
|
}
|
|
15042
|
-
|
|
15043
|
-
texture[4][6] = palette.accent;
|
|
15044
|
-
texture[5][2] = palette.highlight;
|
|
15045
|
-
texture[5][5] = palette.highlight;
|
|
15046
|
-
return texture;
|
|
15672
|
+
return perimeter;
|
|
15047
15673
|
}
|
|
15048
15674
|
|
|
15049
15675
|
/* eslint-disable no-magic-numbers */
|
|
@@ -16648,6 +17274,7 @@ const AVATAR_VISUALS = [
|
|
|
16648
17274
|
octopus3AvatarVisual,
|
|
16649
17275
|
asciiOctopusAvatarVisual,
|
|
16650
17276
|
minecraftAvatarVisual,
|
|
17277
|
+
minecraft2AvatarVisual,
|
|
16651
17278
|
fractalAvatarVisual,
|
|
16652
17279
|
orbAvatarVisual,
|
|
16653
17280
|
];
|
|
@@ -18856,7 +19483,10 @@ function buildTeamSystemMessageBody(teamEntries) {
|
|
|
18856
19483
|
*/
|
|
18857
19484
|
function buildTeamToolDescription(entry) {
|
|
18858
19485
|
const detailLines = collectTeamEntryDetails(entry).map(({ label, content }) => `${label}: ${content}`);
|
|
18859
|
-
return
|
|
19486
|
+
return spaceTrim$1((block) => `
|
|
19487
|
+
Consult teammate ${entry.teammate.label}
|
|
19488
|
+
${block(detailLines.join('\n'))}
|
|
19489
|
+
`);
|
|
18860
19490
|
}
|
|
18861
19491
|
/**
|
|
18862
19492
|
* Collects structured teammate details that should stay visible to the model.
|
|
@@ -24190,7 +24820,10 @@ function createListedTimeoutsAssistantMessage(options) {
|
|
|
24190
24820
|
if (hiddenCount > 0) {
|
|
24191
24821
|
summaryRows.push(`...and ${hiddenCount} more.`);
|
|
24192
24822
|
}
|
|
24193
|
-
return
|
|
24823
|
+
return spaceTrim$1((block) => `
|
|
24824
|
+
Found ${options.total} ${options.total === 1 ? 'timeout' : 'timeouts'}:
|
|
24825
|
+
${block(summaryRows.join('\n'))}
|
|
24826
|
+
`);
|
|
24194
24827
|
}
|
|
24195
24828
|
/**
|
|
24196
24829
|
* Formats one timeout row for assistant-visible timeout listings.
|