@m2c2kit/core 0.3.14 → 0.3.15

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.
Files changed (2) hide show
  1. package/dist/index.js +173 -83
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -175,7 +175,7 @@ class M2c2KitHelpers {
175
175
  entities.push(drawableEntity);
176
176
  const entityPointsArray = entities.map((entity) => {
177
177
  const boundingBox = M2c2KitHelpers.calculateEntityAbsoluteBoundingBox(entity);
178
- return boundingBoxToPoints(boundingBox);
178
+ return M2c2KitHelpers.boundingBoxToPoints(boundingBox);
179
179
  });
180
180
  for (let i = 0; i < entityPointsArray.length; i++) {
181
181
  if (!entityNeedsRotation(entities[i])) {
@@ -183,7 +183,7 @@ class M2c2KitHelpers {
183
183
  }
184
184
  const entityPoints = entityPointsArray[i];
185
185
  const radians = entities[i].zRotation;
186
- const center = findCentroid(entityPoints);
186
+ const center = M2c2KitHelpers.findCentroid(entityPoints);
187
187
  for (let j = i; j < entities.length; j++) {
188
188
  entityPointsArray[j] = rotateRectangle(
189
189
  entityPointsArray[j],
@@ -206,7 +206,7 @@ class M2c2KitHelpers {
206
206
  * @param drawableEntity - Entity to rotate the canvas for
207
207
  */
208
208
  static rotateCanvasForDrawableEntity(canvas, drawableEntity) {
209
- const rotationTransforms = calculateRotationTransforms(drawableEntity);
209
+ const rotationTransforms = M2c2KitHelpers.calculateRotationTransforms(drawableEntity);
210
210
  if (rotationTransforms.length === 0) {
211
211
  return;
212
212
  }
@@ -269,24 +269,167 @@ class M2c2KitHelpers {
269
269
  }
270
270
  return normalized;
271
271
  }
272
+ /**
273
+ * Checks if two points are on the same side of a line.
274
+ *
275
+ * @remarks The line is defined by two points, a and b. The function uses
276
+ * the cross product to determine the relative position of the points.
277
+ *
278
+ * @param p1 - point to check
279
+ * @param p2 - point to check
280
+ * @param a - point that defines one end of the line
281
+ * @param b - point that defines the other end of the line
282
+ * @returns true if p1 and p2 are on the same side of the line, or false
283
+ * otherwise
284
+ */
285
+ static arePointsOnSameSideOfLine(p1, p2, a, b) {
286
+ const cp1 = (b.x - a.x) * (p1.y - a.y) - (b.y - a.y) * (p1.x - a.x);
287
+ const cp2 = (b.x - a.x) * (p2.y - a.y) - (b.y - a.y) * (p2.x - a.x);
288
+ return cp1 * cp2 >= 0;
289
+ }
272
290
  /**
273
291
  * Checks if a point is inside a rectangle.
274
292
  *
293
+ * @remarks The rectangle may have been rotated (sides might not be parallel
294
+ * to the axes).
295
+ *
275
296
  * @param point - The Point to check
276
297
  * @param rect - An array of four Points representing the vertices of the
277
298
  * rectangle in clockwise order
278
299
  * @returns true if the Point is inside the rectangle
279
300
  */
280
301
  static isPointInsideRectangle(point, rect) {
281
- for (let i = 0; i < 4; i++) {
282
- const p1 = rect[i];
283
- const p2 = rect[(i + 1) % 4];
284
- const cross = (p2.x - p1.x) * (point.y - p1.y) - (p2.y - p1.y) * (point.x - p1.x);
285
- if (cross > 0) {
286
- return false;
287
- }
302
+ if (rect.length !== 4) {
303
+ throw new Error("Invalid input: expected an array of four points");
304
+ }
305
+ return M2c2KitHelpers.arePointsOnSameSideOfLine(
306
+ point,
307
+ rect[2],
308
+ rect[0],
309
+ rect[1]
310
+ ) && M2c2KitHelpers.arePointsOnSameSideOfLine(
311
+ point,
312
+ rect[3],
313
+ rect[1],
314
+ rect[2]
315
+ ) && M2c2KitHelpers.arePointsOnSameSideOfLine(
316
+ point,
317
+ rect[0],
318
+ rect[2],
319
+ rect[3]
320
+ ) && M2c2KitHelpers.arePointsOnSameSideOfLine(point, rect[1], rect[3], rect[0]);
321
+ }
322
+ /**
323
+ * Checks if the entity or any of its ancestors have been rotated.
324
+ *
325
+ * @param entity - entity to check
326
+ * @returns true if the entity or any of its ancestors have been rotated
327
+ */
328
+ static entityOrAncestorHasBeenRotated(entity) {
329
+ const entities = entity.ancestors;
330
+ entities.push(entity);
331
+ return entities.some((entity2) => entityNeedsRotation(entity2));
332
+ }
333
+ /**
334
+ * Converts a bounding box to an array of four points representing the
335
+ * vertices of the rectangle.
336
+ *
337
+ * @remarks In m2c2kit, the y-axis is inverted: origin is in the upper-left.
338
+ * Vertices are returned in clockwise order starting from the upper-left.
339
+ *
340
+ * @param boundingBox
341
+ * @returns An array of four points
342
+ */
343
+ static boundingBoxToPoints(boundingBox) {
344
+ const { xMin, xMax, yMin, yMax } = boundingBox;
345
+ const points = [
346
+ { x: xMin, y: yMin },
347
+ // Top left
348
+ { x: xMax, y: yMin },
349
+ // Top right
350
+ { x: xMax, y: yMax },
351
+ // Bottom right
352
+ { x: xMin, y: yMax }
353
+ // Bottom left
354
+ ];
355
+ return points;
356
+ }
357
+ /**
358
+ * Finds the centroid of a rectangle.
359
+ *
360
+ * @param points - An array of four points representing the vertices of the
361
+ * rectangle.
362
+ * @returns array of points representing the centroid of the rectangle.
363
+ */
364
+ static findCentroid(points) {
365
+ if (points.length !== 4) {
366
+ throw new Error("Invalid input: expected an array of four points");
288
367
  }
289
- return true;
368
+ let xSum = 0;
369
+ let ySum = 0;
370
+ for (const point of points) {
371
+ xSum += point.x;
372
+ ySum += point.y;
373
+ }
374
+ const xAvg = xSum / 4;
375
+ const yAvg = ySum / 4;
376
+ return { x: xAvg, y: yAvg };
377
+ }
378
+ /**
379
+ * Rotates a point, counterclockwise, around another point by an angle in
380
+ * radians.
381
+ *
382
+ * @param point - Point to rotate
383
+ * @param radians - angle in radians
384
+ * @param center - Point to rotate around
385
+ * @returns rotated point
386
+ */
387
+ static rotatePoint(point, radians, center) {
388
+ const dx = point.x - center.x;
389
+ const dy = point.y - center.y;
390
+ const x = dx * Math.cos(-radians) - dy * Math.sin(-radians);
391
+ const y = dx * Math.sin(-radians) + dy * Math.cos(-radians);
392
+ return {
393
+ x: x + center.x,
394
+ y: y + center.y
395
+ };
396
+ }
397
+ /**
398
+ * Calculates the rotation transforms to apply to entity, respecting any
399
+ * ancestor rotations.
400
+ *
401
+ * @param drawableEntity - entity to calculate rotation transforms for
402
+ * @returns array of rotation transforms to apply
403
+ */
404
+ static calculateRotationTransforms(drawableEntity) {
405
+ const rotationTransforms = [];
406
+ const entities = drawableEntity.ancestors;
407
+ entities.reverse();
408
+ entities.push(drawableEntity);
409
+ entities.forEach((entity) => {
410
+ if (entityNeedsRotation(entity)) {
411
+ const drawable = entity;
412
+ if (drawable.type === EntityType.Scene) {
413
+ const center2 = {
414
+ x: drawable.absolutePosition.x + drawable.size.width * 0.5,
415
+ y: drawable.absolutePosition.y + drawable.size.height * 0.5
416
+ };
417
+ rotationTransforms.push({
418
+ radians: drawable.zRotation,
419
+ center: center2
420
+ });
421
+ return;
422
+ }
423
+ const boundingBox = M2c2KitHelpers.calculateEntityAbsoluteBoundingBox(drawable);
424
+ const points = M2c2KitHelpers.boundingBoxToPoints(boundingBox);
425
+ const center = M2c2KitHelpers.findCentroid(points);
426
+ rotationTransforms.push({
427
+ radians: drawable.zRotation,
428
+ center
429
+ });
430
+ }
431
+ });
432
+ return rotationTransforms;
290
433
  }
291
434
  }
292
435
  function applyRotationTransformsToCanvas(rotationTransforms, scale, canvas) {
@@ -298,84 +441,16 @@ function applyRotationTransformsToCanvas(rotationTransforms, scale, canvas) {
298
441
  );
299
442
  });
300
443
  }
301
- function calculateRotationTransforms(drawableEntity) {
302
- const rotationTransforms = [];
303
- const entities = drawableEntity.ancestors;
304
- entities.reverse();
305
- entities.push(drawableEntity);
306
- entities.forEach((entity) => {
307
- if (entityNeedsRotation(entity)) {
308
- const drawable = entity;
309
- if (drawable.type === EntityType.Scene) {
310
- const center2 = {
311
- x: drawable.absolutePosition.x + drawable.size.width * 0.5,
312
- y: drawable.absolutePosition.y + drawable.size.height * 0.5
313
- };
314
- rotationTransforms.push({
315
- radians: drawable.zRotation,
316
- center: center2
317
- });
318
- return;
319
- }
320
- const boundingBox = M2c2KitHelpers.calculateEntityAbsoluteBoundingBox(drawable);
321
- const points = boundingBoxToPoints(boundingBox);
322
- const center = findCentroid(points);
323
- rotationTransforms.push({
324
- radians: drawable.zRotation,
325
- center
326
- });
327
- }
328
- });
329
- return rotationTransforms;
330
- }
331
444
  function entityNeedsRotation(entity) {
332
445
  return M2c2KitHelpers.normalizeAngleRadians(entity.zRotation) !== 0 && entity.isDrawable;
333
446
  }
334
- function boundingBoxToPoints(boundingBox) {
335
- const { xMin, xMax, yMin, yMax } = boundingBox;
336
- const points = [
337
- { x: xMin, y: yMin },
338
- // Top left
339
- { x: xMin, y: yMax },
340
- // Bottom left
341
- { x: xMax, y: yMax },
342
- // Bottom right
343
- { x: xMax, y: yMin }
344
- // Top right
345
- ];
346
- return points;
347
- }
348
- function findCentroid(points) {
349
- if (points.length !== 4) {
350
- throw new Error("Invalid input: expected an array of four points");
351
- }
352
- let xSum = 0;
353
- let ySum = 0;
354
- for (const point of points) {
355
- xSum += point.x;
356
- ySum += point.y;
357
- }
358
- const xAvg = xSum / 4;
359
- const yAvg = ySum / 4;
360
- return { x: xAvg, y: yAvg };
361
- }
362
- function rotatePoint(point, radians, center) {
363
- const dx = point.x - center.x;
364
- const dy = point.y - center.y;
365
- const x = dx * Math.cos(-radians) - dy * Math.sin(-radians);
366
- const y = dx * Math.sin(-radians) + dy * Math.cos(-radians);
367
- return {
368
- x: x + center.x,
369
- y: y + center.y
370
- };
371
- }
372
447
  function rotateRectangle(rect, radians, center) {
373
448
  if (rect.length !== 4) {
374
449
  throw new Error("Invalid input: expected an array of four points");
375
450
  }
376
451
  const rotated = [];
377
452
  for (const p of rect) {
378
- rotated.push(rotatePoint(p, radians, center));
453
+ rotated.push(M2c2KitHelpers.rotatePoint(p, radians, center));
379
454
  }
380
455
  return rotated;
381
456
  }
@@ -5748,9 +5823,24 @@ class Game {
5748
5823
  width = radius * 2;
5749
5824
  height = radius * 2;
5750
5825
  }
5751
- const x = domPointerEvent.offsetX;
5752
- const y = domPointerEvent.offsetY;
5826
+ let x = domPointerEvent.offsetX;
5827
+ let y = domPointerEvent.offsetY;
5753
5828
  const bb = M2c2KitHelpers.calculateEntityAbsoluteBoundingBox(entity);
5829
+ if (M2c2KitHelpers.entityOrAncestorHasBeenRotated(entity)) {
5830
+ const transforms = M2c2KitHelpers.calculateRotationTransforms(
5831
+ entity
5832
+ );
5833
+ transforms.forEach((transform) => {
5834
+ const rotatedPoint = M2c2KitHelpers.rotatePoint(
5835
+ { x, y },
5836
+ // take negative because we are applying the reverse rotation
5837
+ -transform.radians,
5838
+ transform.center
5839
+ );
5840
+ x = rotatedPoint.x;
5841
+ y = rotatedPoint.y;
5842
+ });
5843
+ }
5754
5844
  const relativeX = (x - bb.xMin) / (bb.xMax - bb.xMin) * width;
5755
5845
  const relativeY = (y - bb.yMin) / (bb.yMax - bb.yMin) * height;
5756
5846
  return { x: relativeX, y: relativeY };
@@ -7332,7 +7422,7 @@ class Session {
7332
7422
  this.eventListeners = new Array();
7333
7423
  this.sessionDictionary = /* @__PURE__ */ new Map();
7334
7424
  this.initialized = false;
7335
- this.version = "0.3.14 (60325bea)";
7425
+ this.version = "0.3.15 (38470c49)";
7336
7426
  this.options = options;
7337
7427
  for (const activity of this.options.activities) {
7338
7428
  if (this.options.activities.filter((a) => a === activity).length > 1) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m2c2kit/core",
3
- "version": "0.3.14",
3
+ "version": "0.3.15",
4
4
  "description": "The m2c2kit core functionality",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -36,7 +36,7 @@
36
36
  "@rollup/plugin-commonjs": "25.0.7",
37
37
  "@rollup/plugin-node-resolve": "15.2.3",
38
38
  "@rollup/plugin-replace": "5.0.5",
39
- "@types/jest": "29.5.10",
39
+ "@types/jest": "29.5.11",
40
40
  "@types/jsdom": "21.1.6",
41
41
  "@webgpu/types": "0.1.40",
42
42
  "canvas": "2.11.2",
@@ -48,14 +48,14 @@
48
48
  "jest-environment-jsdom": "29.7.0",
49
49
  "jsdom": "23.0.1",
50
50
  "rimraf": "5.0.5",
51
- "rollup": "4.6.1",
51
+ "rollup": "4.8.0",
52
52
  "rollup-plugin-copy": "3.5.0",
53
53
  "rollup-plugin-dts": "6.1.0",
54
54
  "rollup-plugin-esbuild": "6.1.0",
55
55
  "rollup-plugin-polyfill-node": "0.13.0",
56
56
  "ts-jest": "29.1.1",
57
- "ts-node": "10.9.1",
58
- "typescript": "5.3.2"
57
+ "ts-node": "10.9.2",
58
+ "typescript": "5.3.3"
59
59
  },
60
60
  "engines": {
61
61
  "node": ">=18"