Skip to content

Commit

Permalink
readme
Browse files Browse the repository at this point in the history
  • Loading branch information
averrin committed Jul 17, 2022
1 parent 637fffe commit 011d9f9
Show file tree
Hide file tree
Showing 12 changed files with 156 additions and 187 deletions.
143 changes: 4 additions & 139 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Are you annoyed with assigning a single tag for a huge bunch of tiles? Or with m
Just select all your tiles (or tokens) and drag&drop the tag to assign it. Choose a color for it (useless but fancy) and create an action: toggle your tiles' visibility or fire the Active Tiles' trigger.
Your actions are stored in the scene's data so that you can have many of them. The global tags are global; let's be consistent across the scenes!

Director sometimes looks too complex, so read [Documentation](https://github.com/averrin/director/wiki/How-to-use.-With-examples.). It contains a couple of easy to go examples.

## Hints
- you can drag and drop tags
- right click on tag opens a color picker
Expand All @@ -29,155 +31,18 @@ It's not going to be MATT's alternative, so actions are pretty basic
* Sequencer [BETA, required]
* Token Magic FX [Virtual Sequencer's section]

## Sequencer support progress
<details>
<summary>Effects</summary>

### Generic Methods
- [x] Wait Until Finished
- [x] Async
- [x] Repeats
- [x] Play if
- [x] Delay
- [x] Fade In
- [x] Fade Out
- [x] Duration
- [x] Opacity
- [x] Start Time
- [x] Start Time Percentage
- [x] End Time
- [x] End Time Percentage
- [x] Time Range
- [x] Locally
- [ ] For Users
### Effect Methods
- [ ] Base folder
- [x] File
- [x] From
- [x] At location
- [x] Attach To
- [x] Rotate Towards
- [x] Stretch To
- [x] Move Towards
- [x] Move Speed
- [x] Snap to Grid
- [x] Offset
- [x] Sprite Offset
- [x] Zero Sprite Rotation
- [x] Persist
- [x] No Loop
- [x] Extra End Duration
- [x] Origin
- [x] Name
- [x] Private
- [x] Missed
- [ ] Add override
- [ ] Set mustache
- [x] Size (partially)
- [x] Scale
- [x] Scale In
- [x] Scale Out
- [x] Scale To Object
- [x] Anchor (partially)
- [x] Sprite Anchor (partially)
- [x] Center
- [x] Mirror
- [x] Randomize mirror
- [x] Rotate
- [x] Rotate In
- [x] Rotate Out
- [x] Random rotation
- [x] Playback rate
- [x] Below tokens
- [x] Below tiles
- [x] Above lighting
- [x] Z-Index
- [ ] Animate Property
- [ ] Loop Property
- [ ] Filter
- [x] Tint (without picker)
- [x] Screen Space
- [x] Screen Space Above UI
- [x] Screen Space Position
- [x] Screen Space Anchor
- [ ] Screen Space Scale
- [x] Text (fill + fontSize)
- [x] XRay
- [x] Mask
</details>

<details>
<summary>Animation</summary>

### Generic Methods
- [x] Wait Until Finished
- [x] Async
- [x] Repeats
- [x] Play if
- [x] Delay
- [x] Opacity
- [x] Fade In
- [x] Fade Out
- [x] Duration
- [x] Volume
- [x] Fade In Audio
- [x] Audio Out Audio
### Animation Methods
- [x] On
- [x] Move Towards
- [x] Move Speed
- [x] Rotate Towards
- [x] Teleport To
- [x] Offset
- [x] Closest Square
- [x] Snap to Grid
- [x] Rotate
- [x] Rotate In
- [x] Rotate Out
- [x] Tint
- [x] Hide
- [x] Show
</details>

<details>
<summary>Sound</summary>

### Generic Methods
- [x] Wait Until Finished
- [x] Async
- [x] Repeats
- [x] Play if
- [x] Delay
- [x] Duration
- [x] Volume
- [x] Fade In Audio
- [x] Audio Out Audio
- [x] Start Time
- [x] Start Time Percentage
- [x] End Time
- [x] End Time Percentage
- [x] Time Range
- [x] Locally
- [ ] For Users
### Sound methods
- [ ] Base folder
- [x] File
- [ ] Add override
- [ ] Set mustache
</details>

## Plans
- [ ] Documentation
- [ ] v10 support
- [ ] Beginner / Expert UI mode
- [ ] Better import / export
- [X] Better support of Sequencer's functions and types
- [ ] Better support of Sequencer's functions and types
- [ ] Better support for Token Magic FX
- [ ] Support for Dynamic Active Effects
- [ ] Hooks for ending effects of a sequence. E.g. to destroy DAE's effects.
- [ ] [Alpha HUD](https://github.com/averrin/alpha-hud) integrations. A scene widget with something like the hotbar.

## Images
## Images (quite outdated, see docs)
![toolbar](/assets/toolbar.png)
![selection](/assets/selection.png)
![actions](/assets/actions.png)
Expand Down
22 changes: 21 additions & 1 deletion src/constants.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
export const moduleId = "director";

export function evalExpression(expr, ...args) {
let code = `try {return ${expr}} catch(e) {return false}`;
const f = new Function("...args", code);
return f(...args)
}

// import { foundry } from '../modules/foundry.js';
// import { moduleId, SETTINGS } from '../constants.js';

Expand All @@ -15,6 +21,7 @@ export const SETTINGS = {
MANUAL_MODE: "warpgate-mode",
SELECTED_SEQ: "selected-seq",
SELECTED_TAB: "selected-tab",
HIDE_IMPORT: "hide-import",
};

export const HOOKS = [
Expand Down Expand Up @@ -244,6 +251,18 @@ export const hookSpecs = [
return f(...args)
}, args: [{ type: "expression", label: "test" }]
},
{
id: "#onUpdateToken", parents: ["updateToken"], test: (prop, ...args) => {
let code = `try {return ${prop}} catch(e) {return false}`;
const f = new Function("...args", code);
return f(...args)
}, args: [{ type: "expression", label: "test" }]
},
{
id: "#setInterval", parents: [], test: (prop, ...args) => {
return evalExpression(prop, ...args);
}, args: [{ type: "expression", label: "test" }, { type: "expression", label: "interval" }]
},
];

export const argSpecs = [
Expand Down Expand Up @@ -325,7 +344,8 @@ export const argSpecs = [
{ value: "#onTokenProperty", label: "On Token's property" },
{ value: "#onActorProperty", label: "On Actor's property" },
{ value: "#onUpdateToken", label: "Generic updateToken" },
{ value: "#onUpdateActor", label: "Generic updateActor" },]
{ value: "#onUpdateActor", label: "Generic updateActor" },
{ value: "#setInterval", label: "Set Interval" },]
},
{
id: "effectSource", var_types: ["effect"], options: [
Expand Down
40 changes: 37 additions & 3 deletions src/modules/HookManager.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { logger, calculateValueSync } from './helpers.js';
import { logger, calculateValueSync, evalExpression } from './helpers.js';
import { hookSpecs, moduleId, SETTINGS } from '../constants.js';

class HookManager {
Expand All @@ -22,7 +22,6 @@ class HookManager {

getHandler(parent) {
return (...args) => {
logger.info(this.#hooks);
for (const hook of this.#hooks) {
if (!hook.enabled || !hook.event || !hook.target) continue;
let targets = calculateValueSync(hook.target);
Expand Down Expand Up @@ -88,7 +87,17 @@ class HookManager {

updateHandlers() {
for (const [hook, handler] of Object.entries(this.#handlers)) {
if (this.#hooks.some(h => h.enabled && hookSpecs.find(s => s.id == h.event)?.parents.includes(hook))) {
if (hook.startsWith("#setInterval")) {
if (this.#hooks.some(h => h.enabled && `${h.event}-${h.args[1]}` == hook)) {
continue;
} else {
globalThis.Hooks.off(hook, handler);
delete this.#handlers[hook]
logger.info(`Hook: ${hook}#${handler} was uninstalled.`)
logger.info(this.#handlers);
}
} else if (this.#hooks.some(h => h.enabled &&
hookSpecs.find(s => s.id == h.event)?.parents.includes(hook))) {
continue;
} else if (this.#actions.some(a => this.isActionListen(a, hook))) {
continue;
Expand All @@ -101,6 +110,24 @@ class HookManager {
}
}

getIntervalHandler(hook) {
return (...args) => {
logger.info("interval handler called");
const interval = evalExpression(hook.args[1])
setTimeout(() => {
const spec = hookSpecs.find(s => s.id == hook.event);
const id = `${spec.id}-${hook.args[1]}`;
if (id in this.#handlers) {
if (hook.enabled, spec.test(...hook.args, ...args)) {
logger.info(`Interval hook ${hook.getHookName()} was called`, hook);
globalThis.Hooks.call(hook.getHookName(), ...hook.args);
}
this.#handlers[id]();
}
}, interval);
}
}

async onHooksChange(hooks) {
this.#hooks = hooks;
this.updateHandlers();
Expand All @@ -113,6 +140,13 @@ class HookManager {
logger.info(`Hook: ${parent}#${this.#handlers[parent]} was installed.`);
logger.info(this.#handlers);
}
if (spec.id == "#setInterval") {
const id = `${spec.id}-${hook.args[1]}`;
if (id in this.#handlers) continue;
this.#handlers[id] = this.getIntervalHandler(hook);
this.#handlers[id]();
logger.info(`Hook: ${id}#${this.#handlers[id]} was installed.`);
}
}

}
Expand Down
8 changes: 7 additions & 1 deletion src/modules/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export function calculateValueSync(val, type, seq) {
} else if (Array.isArray(val)) {
val = globalThis.Tagger.getByTag(val);
if (type != "selection") {
if (val.length > 0) val = val[0];
if (val.length > 0) val = globalThis.Sequencer.Helpers.random_array_element(val);
}
}
return val;
Expand All @@ -146,3 +146,9 @@ export async function calculateValue(val, type, seq) {
}
return calculateValueSync(val, type, seq)
}

export function evalExpression(expr, ...args) {
let code = `try {return ${expr}} catch(e) {return false}`;
const f = new Function("...args", code);
return f(...args)
}
9 changes: 9 additions & 0 deletions src/modules/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,13 @@ export function initSettings(app) {
default: 2,
type: Number,
});

game.settings.register(moduleId, SETTINGS.HIDE_IMPORT, {
name: "Disable import/export feature",
hint: "Just hide buttons if you don't need it",
scope: "world",
config: true,
default: false,
type: Boolean,
});
}
4 changes: 3 additions & 1 deletion src/styles/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@
max-width: 600px;
border-radius: var(--rounded-btn, 0.5rem);
background: #fff !important;
height: 3rem !important;

input, .selection {
font-size: 1rem !important;
font-size: 1rem !important;
height: 3rem !important;
}
}

Expand Down
19 changes: 10 additions & 9 deletions src/view/MainUI.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
import { HsvPicker } from "svelte-color-picker";
import { tagColors, currentScene } from "../modules/stores.js";
import { tagColors, currentScene, actions } from "../modules/stores.js";
import { getContext } from "svelte";
import Action from "../modules/Actions";
const { application } = getContext("external");
const position = application.position;
position.scale = game.settings.get(moduleId, SETTINGS.UI_SCALE);
Expand All @@ -38,13 +39,9 @@
}
function createAction(_, tags) {
currentScene.update((scene) => {
let actions =
"director-actions" in scene.data.flags ? scene.data.flags["director-actions"].filter((a) => a) : [];
actions = [{ id: uuidv4(), tags: tags, type: "" }, ...actions];
scene.data.flags["director-actions"] = actions;
scene.update({ "flags.director-actions": actions });
return scene;
actions.update((actions) => {
actions = [Action.fromPlain({ id: uuidv4(), value: tags, type: "" }), ...actions];
return actions;
});
mode = "actions";
}
Expand All @@ -64,6 +61,10 @@
mode = t.mode;
globalThis.game.settings.set(moduleId, SETTINGS.SELECTED_TAB, mode);
}
let availableTabs = tabs;
if (setting(SETTINGS.HIDE_IMPORT)) {
availableTabs = availableTabs.filter((t) => t.mode != "import");
}
</script>

<input type="checkbox" id="color-modal" class="ui-modal-toggle" bind:checked={pickerOpen} />
Expand All @@ -79,7 +80,7 @@
<main class="director-ui">
<TagsBar {onTagClick} />
<div class="ui-tabs ui-tabs-boxed">
{#each tabs as t (t.title)}
{#each availableTabs as t (t.title)}
<a class="ui-tab ui-tab-lg" on:click={() => selectMode(t)} class:ui-tab-active={t.mode == mode}>
{t.title}
{#if t.badge}
Expand Down
Loading

0 comments on commit 011d9f9

Please sign in to comment.