From a074ed34f0cfff8fa44d239a118e8ec740e1b4a9 Mon Sep 17 00:00:00 2001 From: lgtst Date: Thu, 26 Jan 2023 09:45:31 +0000 Subject: [PATCH 1/3] blurfilter for image stim v0; --- src/visual/ImageStim.js | 64 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/src/visual/ImageStim.js b/src/visual/ImageStim.js index f043579..8d73be3 100644 --- a/src/visual/ImageStim.js +++ b/src/visual/ImageStim.js @@ -47,10 +47,34 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin) * @param {boolean} [options.autoDraw= false] - whether or not the stimulus should be automatically drawn on every frame flip * @param {boolean} [options.autoLog= false] - whether or not to log */ - constructor({ name, win, image, mask, pos, anchor, units, ori, size, color, opacity, contrast, texRes, depth, interpolate, flipHoriz, flipVert, autoDraw, autoLog } = {}) + constructor({ + name, + win, + image, + mask, + pos, + anchor, + units, + ori, + size, + color, + opacity, + contrast, + texRes, + depth, + interpolate, + flipHoriz, + flipVert, + autoDraw, + autoLog, + blurVal + } = {}) { super({ name, win, units, ori, opacity, depth, pos, anchor, size, autoDraw, autoLog }); + // Holds an instance of PIXI blur filter. Used if blur value is passed. + this._blurFilter = undefined; + this._addAttribute( "image", image, @@ -94,6 +118,11 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin) false, this._onChange(false, false), ); + this._addAttribute( + "blurVal", + blurVal, + 0 + ); // estimate the bounding box: this._estimateBoundingBox(); @@ -234,6 +263,33 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin) } } + setBlurVal (blurVal = 0, log = false) + { + this._setAttribute("blurVal", blurVal, log); + if (this._pixi instanceof PIXI.Sprite) + { + if (this._blurFilter === undefined) + { + this._blurFilter = new PIXI.filters.BlurFilter(); + this._blurFilter.blur = blurVal; + } + else + { + this._blurFilter.blur = blurVal; + } + + // this._pixi might get destroyed and recreated again with no filters. + if (this._pixi.filters instanceof Array && this._pixi.filters.indexOf(this._blurFilter) === -1) + { + this._pixi.filters.push(this._blurFilter); + } + else + { + this._pixi.filters = [this._blurFilter]; + } + } + } + /** * Estimate the bounding box. * @@ -276,6 +332,7 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin) if (typeof this._pixi !== "undefined") { + this._pixi.filters = null; this._pixi.destroy(true); } this._pixi = undefined; @@ -359,6 +416,11 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin) this._pixi.position = to_pixiPoint(this.pos, this.units, this.win); this._pixi.rotation = -this.ori * Math.PI / 180; + if (this._blurVal > 0) + { + this.setBlurVal(this._blurVal); + } + // re-estimate the bounding box, as the texture's width may now be available: this._estimateBoundingBox(); } From 30c937b2138084bc8c996bd7b826aedaef2bcb26 Mon Sep 17 00:00:00 2001 From: lgtst Date: Mon, 13 Feb 2023 19:40:22 +0000 Subject: [PATCH 2/3] progress bar component prototype. --- src/visual/Progress.js | 133 +++++++++++++++++++++++++++++++++++++++++ src/visual/index.js | 1 + 2 files changed, 134 insertions(+) create mode 100644 src/visual/Progress.js diff --git a/src/visual/Progress.js b/src/visual/Progress.js new file mode 100644 index 0000000..279d4d4 --- /dev/null +++ b/src/visual/Progress.js @@ -0,0 +1,133 @@ +import * as PIXI from "pixi.js-legacy"; +import * as util from "../util/Util.js"; +import { Color } from "../util/Color.js"; +import { to_pixiPoint } from "../util/Pixi.js"; +import { VisualStim } from "./VisualStim.js"; + +export class Progress extends VisualStim +{ + constructor ( + { + name, + win, + units, + ori, + opacity, + depth, + pos, + anchor = "left", + size = [300, 30], + clipMask, + autoDraw, + autoLog, + progress = 1, + type, + fillColor, + fillTexture + }) + { + super({ + name, + win, + units, + ori, + opacity, + depth, + pos, + anchor, + size, + clipMask, + autoDraw, + autoLog + }); + + this._addAttribute("progress", progress, 0); + this._addAttribute("type", type, PROGRESS_TYPES.BAR); + this._addAttribute("fillColor", fillColor, "lightgreen"); + this._addAttribute("fillTexture", fillTexture, PIXI.Texture.WHITE); + } + + setProgress (progress = 0, log = false) + { + this._setAttribute("progress", Math.min(1.0, Math.max(0.0, progress)), log); + if (this._pixi !== undefined) + { + this._pixi.clear(); + const size_px = util.to_px(this.size, this.units, this.win); + const pos_px = util.to_px(this.pos, this.units, this.win); + const progressWidth = size_px[0] * this._progress; + if (this._fillTexture) + { + let t = PIXI.Texture.WHITE; + if (typeof this._fillTexture === "string") + { + t = PIXI.Texture.from(this._fillTexture); + t.baseTexture.scaleMode = PIXI.SCALE_MODES.NEAREST; + } + this._pixi.beginTextureFill({ + texture: t + }); + } + else + { + this._pixi.beginFill(new Color(this._fillColor).int, this._opacity); + } + if (this._type === PROGRESS_TYPES.BAR) + { + this._pixi.drawRect(pos_px[0], pos_px[1], progressWidth, size_px[1]); + } + // TODO: check out beginTextureFill(). Perhaps it will allow to use images as filling for progress. + this._pixi.endFill(); + + // TODO: is there a better way to ensure anchor works? + this.anchor = this._anchor; + } + } + + /** + * Update the stimulus, if necessary. + * + * @protected + */ + _updateIfNeeded() + { + // TODO: figure out what is the error with estimateBoundBox on resize? + if (!this._needUpdate) + { + return; + } + this._needUpdate = false; + + // update the PIXI representation, if need be: + if (this._needPixiUpdate) + { + this._needPixiUpdate = false; + + if (typeof this._pixi !== "undefined") + { + this._pixi.destroy(true); + } + this._pixi = new PIXI.Graphics(); + // TODO: Should we do this? + // this._pixi.lineStyle(this._lineWidth, this._lineColor.int, this._opacity, 0.5); + + // TODO: Should just .setProgress() be called? + this.setProgress(this._progress); + + this._pixi.scale.y = -1; + this._pixi.zIndex = -this._depth; + this.anchor = this._anchor; + } + + // set polygon position and rotation: + // TODO: what's the difference bw to_px and to_pixiPoint? + this._pixi.position = to_pixiPoint(this.pos, this.units, this.win); + this._pixi.rotation = -this.ori * Math.PI / 180.0; + } +} + +export const PROGRESS_TYPES = +{ + BAR: 0, + CIRCLE: 1 +} diff --git a/src/visual/index.js b/src/visual/index.js index 8c604fa..07c75b0 100644 --- a/src/visual/index.js +++ b/src/visual/index.js @@ -13,3 +13,4 @@ export * from "./TextStim.js"; export * from "./VisualStim.js"; export * from "./FaceDetector.js"; export * from "./Survey.js"; +export * from "./Progress.js"; From 122250527c1cb0040e4b1c62c2ca0ed456db221c Mon Sep 17 00:00:00 2001 From: Alain Pitiot Date: Wed, 19 Jul 2023 09:55:49 +0200 Subject: [PATCH 3/3] log in constructor, additional comment --- src/visual/Progress.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/visual/Progress.js b/src/visual/Progress.js index 279d4d4..3963a54 100644 --- a/src/visual/Progress.js +++ b/src/visual/Progress.js @@ -45,8 +45,16 @@ export class Progress extends VisualStim this._addAttribute("type", type, PROGRESS_TYPES.BAR); this._addAttribute("fillColor", fillColor, "lightgreen"); this._addAttribute("fillTexture", fillTexture, PIXI.Texture.WHITE); + + if (this._autoLog) + { + this._psychoJS.experimentLogger.exp(`Created ${this.name} = ${this.toString()}`); + } } + /** + * Setter for the progress attribute. + */ setProgress (progress = 0, log = false) { this._setAttribute("progress", Math.min(1.0, Math.max(0.0, progress)), log);