All user data for FoundryVTT. Includes worlds, systems, modules, and any asset in the "foundryuserdata" directory. Does NOT include the FoundryVTT installation itself.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

220 lines
7.7 KiB

1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
  1. let circularMaskTexture = null;
  2. function countEffects(token) {
  3. if (!token) {
  4. return 0;
  5. }
  6. let numEffects = token.document.effects?.length || 0;
  7. token.actor?.temporaryEffects?.forEach((actorEffect) => {
  8. if (!actorEffect.getFlag("core", "overlay")) {
  9. numEffects++;
  10. }
  11. });
  12. return numEffects;
  13. }
  14. function sortIcons(e1, e2) {
  15. if (e1.position.x === e2.position.x) {
  16. return e1.position.y - e2.position.y;
  17. }
  18. return e1.position.x - e2.position.x;
  19. }
  20. function updateIconSize(effectIcon, size) {
  21. effectIcon.width = size;
  22. effectIcon.height = size;
  23. }
  24. function polar_to_cartesian(r, theta) {
  25. return {
  26. x: r * Math.cos(theta),
  27. y: r * Math.sin(theta),
  28. };
  29. }
  30. function updateIconPosition(effectIcon, i, effectIcons, token) {
  31. const actorSize = token?.actor?.size;
  32. let max = 20;
  33. if (actorSize == "tiny") max = 10;
  34. if (actorSize == "sm") max = 14;
  35. if (actorSize == "med") max = 16;
  36. const ratio = i / max;
  37. // const angularOffset = i < max ? 0 : ratio / 2;
  38. const gridSize = token?.scene?.grid?.size ?? 100;
  39. const tokenTileFactor = token?.document?.width ?? 1;
  40. const sizeOffset = sizeToOffset(actorSize);
  41. const offset = sizeOffset * tokenTileFactor * gridSize;
  42. const initialRotation = (0.5 + (1 / max) * Math.PI) * Math.PI;
  43. const { x, y } = polar_to_cartesian(offset, (ratio + 0) * 2 * Math.PI + initialRotation);
  44. // debugger;
  45. effectIcon.position.x = x / 2 + (gridSize * tokenTileFactor) / 2;
  46. effectIcon.position.y = (-1 * y) / 2 + (gridSize * tokenTileFactor) / 2;
  47. }
  48. // Nudge icons to be on the token ring or slightly outside
  49. function sizeToOffset(size) {
  50. if (size == "tiny") {
  51. return 1.4;
  52. } else if (size == "sm") {
  53. return 1.0;
  54. } else if (size == "med") {
  55. return 1.2;
  56. } else if (size == "lg") {
  57. return 0.925;
  58. } else if (size == "huge") {
  59. return 0.925;
  60. } else if (size == "grg") {
  61. return 0.925;
  62. }
  63. return 1.0;
  64. }
  65. function sizeToIconScale(size) {
  66. if (size == "tiny") {
  67. return 1.4;
  68. } else if (size == "sm") {
  69. return 1.4;
  70. } else if (size == "med") {
  71. return 1.4;
  72. } else if (size == "lg") {
  73. return 1.25;
  74. } else if (size == "huge") {
  75. return 1.55;
  76. } else if (size == "grg") {
  77. return 2.2;
  78. }
  79. return 1.0;
  80. }
  81. function drawBG(effectIcon, background, gridScale) {
  82. const r = effectIcon.width / 2;
  83. const isDorakoUiActive = game.modules.get("pf2e-dorako-ui")?.active;
  84. const appTheme = isDorakoUiActive ? game.settings.get("pf2e-dorako-ui", "theme.app-theme") : false;
  85. if (appTheme && appTheme.includes("foundry2")) {
  86. background.lineStyle((1 * gridScale) / 2, 0x302831, 1, 0);
  87. background.drawCircle(effectIcon.position.x, effectIcon.position.y, r + 1 * gridScale);
  88. background.beginFill(0x0b0a13);
  89. background.drawCircle(effectIcon.position.x, effectIcon.position.y, r + 1 * gridScale);
  90. background.endFill();
  91. return;
  92. } else if (appTheme && appTheme.includes("crb")) {
  93. background.lineStyle((1 * gridScale) / 2, 0x956d58, 1, 1);
  94. background.drawCircle(effectIcon.position.x, effectIcon.position.y, r + 1 * gridScale);
  95. background.lineStyle((1 * gridScale) / 2, 0xe9d7a1, 1, 0);
  96. background.drawCircle(effectIcon.position.x, effectIcon.position.y, r + 1 * gridScale);
  97. background.beginFill(0x956d58);
  98. background.drawCircle(effectIcon.position.x, effectIcon.position.y, r + 1 * gridScale);
  99. background.endFill();
  100. return;
  101. } else if (appTheme && appTheme.includes("bg3")) {
  102. background.lineStyle((1 * gridScale) / 2, 0x9a8860, 1, 1);
  103. background.drawCircle(effectIcon.position.x, effectIcon.position.y, r + 1 * gridScale);
  104. background.lineStyle((1 * gridScale) / 2, 0xd3b87c, 1, 0);
  105. background.drawCircle(effectIcon.position.x, effectIcon.position.y, r + 1 * gridScale);
  106. background.beginFill(0x000000);
  107. background.drawCircle(effectIcon.position.x, effectIcon.position.y, r + 1 * gridScale);
  108. background.endFill();
  109. return;
  110. }
  111. // background.lineStyle((1 * gridScale) / 2, 0x222222, 1, 1);
  112. // background.drawCircle(effectIcon.position.x, effectIcon.position.y, r + 1 * gridScale);
  113. background.lineStyle((1 * gridScale) / 2, 0x444444, 1, 0);
  114. background.drawCircle(effectIcon.position.x, effectIcon.position.y, r + 1 * gridScale);
  115. background.beginFill(0x222222);
  116. background.drawCircle(effectIcon.position.x, effectIcon.position.y, r + 1 * gridScale);
  117. background.endFill();
  118. }
  119. function updateEffectScales(token) {
  120. // if (token?.actor?.size == "sm") return;
  121. const numEffects = countEffects(token);
  122. if (numEffects > 0 && token.effects.children.length > 0) {
  123. const background = token.effects.children[0];
  124. if (!(background instanceof PIXI.Graphics)) return;
  125. background.clear();
  126. // Exclude the background and overlay
  127. const effectIcons = token.effects.children.slice(1, 1 + numEffects);
  128. const tokenSize = token?.actor?.size;
  129. const gridSize = token?.scene?.grid?.size ?? 100;
  130. // Reposition and scale them
  131. effectIcons.forEach((effectIcon, i, effectIcons) => {
  132. if (!(effectIcon instanceof PIXI.Sprite)) return;
  133. effectIcon.anchor.set(0.5);
  134. const iconScale = sizeToIconScale(tokenSize);
  135. const gridScale = gridSize / 100;
  136. const scaledSize = 12 * iconScale * gridScale;
  137. updateIconSize(effectIcon, scaledSize);
  138. updateIconPosition(effectIcon, i, effectIcons, token);
  139. drawBG(effectIcon, background, gridScale);
  140. });
  141. }
  142. }
  143. Hooks.once("ready", () => {
  144. const enabled = game.settings.get("pf2e-dorako-ux", "moving.adjust-token-effects-hud");
  145. if (!enabled) return;
  146. const origRefreshEffects = Token.prototype._refreshEffects;
  147. Token.prototype._refreshEffects = function (...args) {
  148. // const enabled = game.settings.get("pf2e-dorako-ux", "ux.adjust-token-effects-hud");
  149. // if (!enabled) {
  150. // origRefreshEffects.apply(this, args);
  151. // return;
  152. // }
  153. if (this) {
  154. origRefreshEffects.apply(this, args);
  155. updateEffectScales(this);
  156. }
  157. };
  158. const origDrawEffect = Token.prototype._drawEffect;
  159. Token.prototype._drawEffect = async function (...args) {
  160. // const enabled = game.settings.get("pf2e-dorako-ux", "ux.adjust-token-effects-hud");
  161. // if (!enabled) {
  162. // origDrawEffect.apply(this, args);
  163. // return;
  164. // }
  165. if (this) {
  166. const src = args[0];
  167. const tint = args[1];
  168. // debugger;
  169. if (!src) return;
  170. let tex = await loadTexture(src, { fallback: "icons/svg/hazard.svg" });
  171. let icon = new PIXI.Sprite(tex);
  172. if (src != game.settings.get("pf2e", "deathIcon")) {
  173. // If the circular mask hasn't been created yet
  174. // if (!circularMaskTexture) {
  175. // // Define a new render texture that is 110x110
  176. // circularMaskTexture = PIXI.RenderTexture.create(110, 110);
  177. // // Define the mask sprite
  178. // const renderedMaskSprite = new PIXI.Graphics().beginFill(0xffffff).drawCircle(55, 55, 55).endFill();
  179. // // Blur the mask sprite
  180. // const blurFilter = new PIXI.filters.BlurFilter(2);
  181. // renderedMaskSprite.filters = [blurFilter];
  182. // // Render the result of the mask sprite to the texture
  183. // canvas.app.renderer.render(renderedMaskSprite, circularMaskTexture);
  184. // }
  185. const minDimension = Math.min(icon.width, icon.height);
  186. // Use the blurred pre-made texture and create a new mask sprite for the specific icon
  187. const myMask = new PIXI.Graphics().beginFill(0xffffff).drawCircle(55, 55, 55).endFill();
  188. //const myMask = new PIXI.Sprite(circularMaskTexture);
  189. //myMask.anchor.set(0.5,0.5);
  190. myMask.width = minDimension;
  191. myMask.height = minDimension;
  192. myMask.x = -icon.width / 2;
  193. myMask.y = -icon.height / 2;
  194. icon.mask = myMask;
  195. icon.addChild(myMask);
  196. }
  197. // debugger;
  198. return this.effects.addChild(icon);
  199. }
  200. };
  201. });