@ikijs/editor 0.18.0 → 0.19.0

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.mjs CHANGED
@@ -2684,7 +2684,11 @@ function headOwnBreath(hasBody) {
2684
2684
  var ELBOW_AT = 0.42;
2685
2685
  var CAP_ROWS = [0.1, 0.3];
2686
2686
  var CAP_SEGMENTS = 12;
2687
- var ARM_RANGE = [-30, 150];
2687
+ var CAP_INSET = 3;
2688
+ var capInset = (i) => Math.round(CAP_INSET * Math.min(1, Math.min(i, CAP_SEGMENTS - i) / 2));
2689
+ var CAP_RIM = 0.25;
2690
+ var ARM_RANGE = [-8, 32];
2691
+ var ELBOW_RANGE = [-10, 90];
2688
2692
  var ARM_PARAMS = {
2689
2693
  arm_L: { arm: P3.ArmLeft, elbow: P3.ElbowLeft },
2690
2694
  arm_R: { arm: P3.ArmRight, elbow: P3.ElbowRight }
@@ -2692,11 +2696,13 @@ var ARM_PARAMS = {
2692
2696
  var ARM_IDS = {
2693
2697
  arm_L: {
2694
2698
  forearm: "forearm_L",
2699
+ cap: "elbow_L",
2695
2700
  armDeformer: "armDeformer_L",
2696
2701
  forearmDeformer: "forearmDeformer_L"
2697
2702
  },
2698
2703
  arm_R: {
2699
2704
  forearm: "forearm_R",
2705
+ cap: "elbow_R",
2700
2706
  armDeformer: "armDeformer_R",
2701
2707
  forearmDeformer: "forearmDeformer_R"
2702
2708
  }
@@ -2749,11 +2755,30 @@ function armGeometry(layer, bodyAxisX) {
2749
2755
  b.x1 - elbow.x,
2750
2756
  b.y1 - elbow.y
2751
2757
  );
2758
+ const inside = (x, y) => {
2759
+ const k = Math.floor(y) - bbox.y;
2760
+ if (k < 0 || k >= bbox.h) return false;
2761
+ const [rs, re] = span(k);
2762
+ return rs < x && x < re;
2763
+ };
2764
+ const capRays = Array.from({ length: CAP_SEGMENTS + 1 }, (_, i) => {
2765
+ const a = Math.PI * i / CAP_SEGMENTS;
2766
+ let t = 1;
2767
+ while (t <= capRadius + CAP_INSET && inside(
2768
+ elbow.x + canvasW / 2 + t * Math.cos(a),
2769
+ canvasH / 2 - elbow.y - t * Math.sin(a)
2770
+ )) {
2771
+ t++;
2772
+ }
2773
+ return Math.min(capRadius, Math.max(1, t - capInset(i)));
2774
+ });
2752
2775
  return {
2753
2776
  shoulder,
2754
2777
  shoulderRadius: ru,
2755
2778
  elbow,
2756
2779
  capRadius,
2780
+ capRays,
2781
+ seamRun: [s - bbox.x, e - bbox.x],
2757
2782
  side: shoulder.x > bodyAxisX ? 1 : -1
2758
2783
  };
2759
2784
  }
@@ -2768,69 +2793,101 @@ function armParts(role, layer, g, order) {
2768
2793
  const lx = (x) => roundTo((x - cx(b)) / bw(b), 1e-5);
2769
2794
  const ly = (y) => roundTo((y - cy(b)) / bh(b), 1e-5);
2770
2795
  const seam = ly(g.elbow.y);
2771
- const band = (top, bottom) => [
2796
+ const band = (top2, bottom) => [
2772
2797
  -0.5,
2773
- top,
2798
+ top2,
2774
2799
  0.5,
2775
- top,
2800
+ top2,
2776
2801
  -0.5,
2777
2802
  bottom,
2778
2803
  0.5,
2779
2804
  bottom
2780
2805
  ];
2781
2806
  const quad = [2, 3, 0, 0, 3, 1];
2782
- const cap = [lx(g.elbow.x), seam];
2807
+ const rays = g.capRays.length;
2808
+ const top = (rays - 1) / 2;
2809
+ const at = (i, r) => {
2810
+ const a = Math.PI * i / (rays - 1);
2811
+ return [lx(g.elbow.x + r * Math.cos(a)), ly(g.elbow.y + r * Math.sin(a))];
2812
+ };
2813
+ const width = (i) => Math.min(CAP_RIM * g.capRadius, g.capRays[i] / 2);
2814
+ const ringRays = Array.from({ length: rays }, (_, i) => i);
2815
+ ringRays.splice(top, 0, top);
2816
+ const vertices = [lx(g.elbow.x), seam];
2817
+ for (let i = 0; i < rays; i++) {
2818
+ vertices.push(...at(i, g.capRays[i] - width(i)));
2819
+ }
2820
+ const ringInner = vertices.length / 2;
2821
+ for (const i of ringRays) vertices.push(...at(i, g.capRays[i] - width(i)));
2822
+ const ringOuter = vertices.length / 2;
2823
+ for (const i of ringRays) vertices.push(...at(i, g.capRays[i]));
2824
+ const { uvs } = meshOf(vertices, []);
2825
+ const col = (c) => roundTo(Math.min(Math.max(c + 0.5, 0.5), bw(b) - 0.5) / bw(b), 1e-5);
2826
+ const v = roundTo(0.5 - seam, 1e-5);
2827
+ ringRays.forEach((i, j) => {
2828
+ const right = j <= top;
2829
+ const outer = right ? g.seamRun[1] : g.seamRun[0] - 1;
2830
+ const step = right ? -width(i) : width(i);
2831
+ uvs[(ringInner + j) * 2] = col(outer + step);
2832
+ uvs[(ringInner + j) * 2 + 1] = v;
2833
+ uvs[(ringOuter + j) * 2] = col(outer);
2834
+ uvs[(ringOuter + j) * 2 + 1] = v;
2835
+ });
2783
2836
  const fan = [];
2784
- for (let i = 0; i <= CAP_SEGMENTS; i++) {
2785
- const a = Math.PI * i / CAP_SEGMENTS;
2786
- cap.push(
2787
- lx(g.elbow.x + g.capRadius * Math.cos(a)),
2788
- ly(g.elbow.y + g.capRadius * Math.sin(a))
2789
- );
2790
- if (i > 0) fan.push(4, 4 + i, 5 + i);
2791
- }
2792
- const part = (id, deformer, at, mesh) => ({
2837
+ for (let i = 0; i < rays - 1; i++) fan.push(0, 1 + i, 2 + i);
2838
+ const ring = [];
2839
+ for (let j = 0; j < ringRays.length - 1; j++) {
2840
+ if (j === top) continue;
2841
+ const [p, q] = [ringInner + j, ringOuter + j];
2842
+ ring.push(p, q, q + 1, p, q + 1, p + 1);
2843
+ }
2844
+ const part = (id, deformer, z, mesh) => ({
2793
2845
  id,
2794
2846
  color: [1, 1, 1, 1],
2795
2847
  width: bw(b),
2796
2848
  height: bh(b),
2797
2849
  transform: { x: cx(b), y: cy(b) },
2798
- order: at,
2850
+ order: z,
2799
2851
  deformer,
2800
2852
  mesh
2801
2853
  });
2802
2854
  const ids = ARM_IDS[role];
2803
2855
  return [
2804
- part(role, ids.armDeformer, order, meshOf(band(0.5, seam), quad)),
2856
+ part(ids.cap, ids.forearmDeformer, order, {
2857
+ vertices,
2858
+ uvs,
2859
+ indices: [...fan, ...ring]
2860
+ }),
2861
+ part(role, ids.armDeformer, order + 1, meshOf(band(0.5, seam), quad)),
2805
2862
  part(
2806
2863
  ids.forearm,
2807
2864
  ids.forearmDeformer,
2808
- order + 1,
2809
- meshOf([...band(seam, -0.5), ...cap], [...quad, ...fan])
2865
+ order + 2,
2866
+ meshOf(band(seam, -0.5), quad)
2810
2867
  )
2811
2868
  ];
2812
2869
  }
2813
2870
  function armDeformers(role, g) {
2814
2871
  const ids = ARM_IDS[role];
2815
2872
  const params = ARM_PARAMS[role];
2816
- const rotate = (parameter) => ({
2873
+ const rotate = (parameter, range, sign) => ({
2817
2874
  parameter,
2818
2875
  channel: "rotate",
2819
- from: g.side * ARM_RANGE[0],
2820
- to: g.side * ARM_RANGE[1]
2876
+ from: sign * range[0],
2877
+ to: sign * range[1]
2821
2878
  });
2822
2879
  return [
2823
2880
  {
2824
2881
  id: ids.armDeformer,
2825
2882
  parent: BODY_WARP_ID,
2826
2883
  pivot: { ...g.shoulder },
2827
- bindings: [rotate(params.arm)]
2884
+ bindings: [rotate(params.arm, ARM_RANGE, g.side)]
2828
2885
  },
2829
2886
  {
2830
2887
  id: ids.forearmDeformer,
2831
2888
  parent: ids.armDeformer,
2832
2889
  pivot: { ...g.elbow },
2833
- bindings: [rotate(params.elbow)]
2890
+ bindings: [rotate(params.elbow, ELBOW_RANGE, -g.side)]
2834
2891
  }
2835
2892
  ];
2836
2893
  }
@@ -2839,8 +2896,8 @@ function armDeformers(role, g) {
2839
2896
  var ROLE_TABLE = [
2840
2897
  { role: "hair_back", family: "hair_back" },
2841
2898
  { role: "body", family: "body" },
2842
- { role: "arm_L", family: "arm", parts: ["arm_L", "forearm_L"] },
2843
- { role: "arm_R", family: "arm", parts: ["arm_R", "forearm_R"] },
2899
+ { role: "arm_L", family: "arm", parts: ["elbow_L", "arm_L", "forearm_L"] },
2900
+ { role: "arm_R", family: "arm", parts: ["elbow_R", "arm_R", "forearm_R"] },
2844
2901
  { role: "face", family: "face", required: true },
2845
2902
  { role: "blush_L", family: "face" },
2846
2903
  { role: "blush_R", family: "face" },
@@ -5659,13 +5716,14 @@ function declareParameters(roles) {
5659
5716
  add(P6.BodyAngleZ, "Body Angle Z", -10, 10, 0);
5660
5717
  }
5661
5718
  const [armMin, armMax] = ARM_RANGE;
5719
+ const [elbowMin, elbowMax] = ELBOW_RANGE;
5662
5720
  if (roles.has("arm_L")) {
5663
5721
  add(P6.ArmLeft, "Arm L", armMin, armMax, 0);
5664
- add(P6.ElbowLeft, "Elbow L", armMin, armMax, 0);
5722
+ add(P6.ElbowLeft, "Elbow L", elbowMin, elbowMax, 0);
5665
5723
  }
5666
5724
  if (roles.has("arm_R")) {
5667
5725
  add(P6.ArmRight, "Arm R", armMin, armMax, 0);
5668
- add(P6.ElbowRight, "Elbow R", armMin, armMax, 0);
5726
+ add(P6.ElbowRight, "Elbow R", elbowMin, elbowMax, 0);
5669
5727
  }
5670
5728
  add(P6.EyeOpenLeft, "Eye L", 0, 1, 1);
5671
5729
  add(P6.EyeOpenRight, "Eye R", 0, 1, 1);