1
0
mirror of https://github.com/psychopy/psychojs.git synced 2025-05-10 18:50:54 +00:00

Merge pull request #595 from psychopy/psychojs_window_bg_image

Psychojs window bg image support
This commit is contained in:
Nikita Agafonov 2024-03-29 01:50:55 +00:00 committed by GitHub
commit 122c84d9fe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 157 additions and 9 deletions

View File

@ -59,6 +59,8 @@ export class Window extends PsychObject
* @param {string} [options.name] the name of the window * @param {string} [options.name] the name of the window
* @param {boolean} [options.fullscr= false] whether or not to go fullscreen * @param {boolean} [options.fullscr= false] whether or not to go fullscreen
* @param {Color} [options.color= Color('black')] the background color of the window * @param {Color} [options.color= Color('black')] the background color of the window
* @param {string | HTMLImageElement} [options.backgroundImage = ""] - background image of the window.
* @param {string} [options.backgroundFit = "cover"] - how to fit background image in the window.
* @param {number} [options.gamma= 1] sets the divisor for gamma correction. In other words gamma correction is calculated as pow(rgb, 1/gamma) * @param {number} [options.gamma= 1] sets the divisor for gamma correction. In other words gamma correction is calculated as pow(rgb, 1/gamma)
* @param {number} [options.contrast= 1] sets the contrast value * @param {number} [options.contrast= 1] sets the contrast value
* @param {string} [options.units= 'pix'] the units of the window * @param {string} [options.units= 'pix'] the units of the window
@ -71,6 +73,8 @@ export class Window extends PsychObject
name, name,
fullscr = false, fullscr = false,
color = new Color("black"), color = new Color("black"),
backgroundImage = "",
backgroundFit = "cover",
gamma = 1, gamma = 1,
contrast = 1, contrast = 1,
units = "pix", units = "pix",
@ -93,11 +97,7 @@ export class Window extends PsychObject
this._drawList = []; this._drawList = [];
this._addAttribute("fullscr", fullscr); this._addAttribute("fullscr", fullscr);
this._addAttribute("color", color, new Color("black"), () => { this._addAttribute("color", color, new Color("black"));
if (this._backgroundSprite) {
this._backgroundSprite.tint = this._color.int;
}
});
this._addAttribute("gamma", gamma, 1, () => { this._addAttribute("gamma", gamma, 1, () => {
this._adjustmentFilter.gamma = this._gamma; this._adjustmentFilter.gamma = this._gamma;
}); });
@ -108,6 +108,8 @@ export class Window extends PsychObject
this._addAttribute("waitBlanking", waitBlanking); this._addAttribute("waitBlanking", waitBlanking);
this._addAttribute("autoLog", autoLog); this._addAttribute("autoLog", autoLog);
this._addAttribute("size", []); this._addAttribute("size", []);
this._addAttribute("backgroundImage", backgroundImage, "");
this._addAttribute("backgroundFit", backgroundFit, "cover");
// setup PIXI: // setup PIXI:
this._setupPixi(); this._setupPixi();
@ -139,6 +141,12 @@ export class Window extends PsychObject
} }
} }
static BACKGROUND_FIT_ENUM = {
cover: 0,
contain: 1,
auto: 2
};
/** /**
* Close the window. * Close the window.
* *
@ -360,6 +368,134 @@ export class Window extends PsychObject
this._refresh(); this._refresh();
} }
/**
* Set background image of the window.
*
* @name module:core.Window#setBackgroundImage
* @function
* @public
* @param {string} backgroundImage - name of the image resource (should be one specified in resource manager)
* @param {boolean} log - whether or not to log
*/
setBackgroundImage (backgroundImage = "", log = false)
{
this._setAttribute("backgroundImage", backgroundImage, log);
if (this._backgroundSprite === undefined)
{
return;
}
let imgResource = backgroundImage;
if (this._backgroundSprite instanceof PIXI.Sprite && this._backgroundSprite.texture !== PIXI.Texture.WHITE)
{
this._backgroundSprite.texture.destroy(true);
}
if (typeof backgroundImage === "string" && backgroundImage.length > 0)
{
imgResource = this.psychoJS.serverManager.getResource(backgroundImage);
}
if (imgResource instanceof HTMLImageElement)
{
const texOpts =
{
scaleMode: PIXI.SCALE_MODES.LINEAR
};
this._backgroundSprite.texture = new PIXI.Texture(new PIXI.BaseTexture(imgResource, texOpts));
this._backgroundSprite.tint = 0xffffff;
this.backgroundFit = this._backgroundFit;
}
else
{
this._backgroundSprite.texture = PIXI.Texture.WHITE;
this._backgroundSprite.width = this._size[0];
this._backgroundSprite.height = this._size[1];
this._backgroundSprite.anchor.set(.5);
this.color = this._color;
}
}
/**
* Set fit mode for background image of the window.
*
* @name module:core.Window#setBackgroundFit
* @function
* @public
* @param {string} [backgroundFit = "cover"] - fit mode for background image ["cover", "contain", "scaledown", "none"].
* @param {boolean} log - whether or not to log
*/
setBackgroundFit (backgroundFit = "cover", log = false)
{
if (this._backgroundImage === "")
{
return;
}
const backgroundFitCode = Window.BACKGROUND_FIT_ENUM[backgroundFit.replace("-", "").toLowerCase()];
if (backgroundFitCode === undefined)
{
return;
}
this._setAttribute("backgroundFit", backgroundFit, log);
const backgroundAspectRatio = this._backgroundSprite.texture.width / this._backgroundSprite.texture.height;
const windowAspectRatio = this._size[0] / this._size[1];
if (backgroundFitCode === Window.BACKGROUND_FIT_ENUM.cover)
{
if (windowAspectRatio >= backgroundAspectRatio)
{
this._backgroundSprite.width = this._size[0];
this._backgroundSprite.height = this._size[0] / backgroundAspectRatio;
}
else
{
this._backgroundSprite.height = this._size[1];
this._backgroundSprite.width = this._size[1] * backgroundAspectRatio;
}
}
else if (backgroundFitCode === Window.BACKGROUND_FIT_ENUM.contain)
{
if (windowAspectRatio >= backgroundAspectRatio)
{
this._backgroundSprite.height = this._size[1];
this._backgroundSprite.width = this._size[1] * backgroundAspectRatio;
}
else
{
this._backgroundSprite.width = this._size[0];
this._backgroundSprite.height = this._size[0] / backgroundAspectRatio;
}
}
else if (backgroundFitCode === Window.BACKGROUND_FIT_ENUM.auto)
{
this._backgroundSprite.width = this._backgroundSprite.texture.width;
this._backgroundSprite.height = this._backgroundSprite.texture.height;
}
}
/**
* Set foreground color value for the window.
*
* @name module:visual.Window#setColor
* @public
* @param {Color} colorVal - color value, can be String like "red" or "#ff0000" or Number like 0xff0000.
* @param {boolean} [log= false] - whether of not to log
*/
setColor(colorVal = "white", log = false)
{
const colorObj = (colorVal instanceof Color) ? colorVal : new Color(colorVal, Color.COLOR_SPACE.RGB);
this._setAttribute("color", colorObj, log);
if (this._backgroundSprite && !this._backgroundImage)
{
this._backgroundSprite.tint = this._color.int;
}
}
/** /**
* Update this window, if need be. * Update this window, if need be.
* *
@ -372,7 +508,7 @@ export class Window extends PsychObject
if (this._renderer) if (this._renderer)
{ {
this._renderer.backgroundColor = this._color.int; this._renderer.backgroundColor = this._color.int;
this._backgroundSprite.tint = this._color.int; this.color = this._color;
} }
// we also change the background color of the body since // we also change the background color of the body since
@ -466,6 +602,7 @@ export class Window extends PsychObject
// background sprite so that if we need to move all stims at once, the background sprite // background sprite so that if we need to move all stims at once, the background sprite
// won't get affected. // won't get affected.
this._backgroundSprite = new PIXI.Sprite(PIXI.Texture.WHITE); this._backgroundSprite = new PIXI.Sprite(PIXI.Texture.WHITE);
this._backgroundSprite.scale.y = -1;
this._backgroundSprite.tint = this.color.int; this._backgroundSprite.tint = this.color.int;
this._backgroundSprite.width = this._size[0]; this._backgroundSprite.width = this._size[0];
this._backgroundSprite.height = this._size[1]; this._backgroundSprite.height = this._size[1];
@ -588,8 +725,15 @@ export class Window extends PsychObject
} }
Window._resizePixiRenderer(this, e); Window._resizePixiRenderer(this, e);
if (this._backgroundImage === undefined)
{
this._backgroundSprite.width = this._size[0]; this._backgroundSprite.width = this._size[0];
this._backgroundSprite.height = this._size[1]; this._backgroundSprite.height = this._size[1];
}
else
{
this.backgroundFit = this._backgroundFit;
}
this._fullRefresh(); this._fullRefresh();
}; };
window.addEventListener("resize", this._resizeCallback); window.addEventListener("resize", this._resizeCallback);

View File

@ -67,6 +67,10 @@ psychoJS.start({
expInfo: expInfo, expInfo: expInfo,
configURL: "../config.json", configURL: "../config.json",
resources: [ resources: [
{
name: "starformation.jpg",
path: "./test_resources/starformation.jpg"
},
{ {
name: "cool.gif", name: "cool.gif",
path: "./test_resources/cool.gif" path: "./test_resources/cool.gif"
@ -132,7 +136,7 @@ async function experimentInit() {
// Initialize components for Routine "instruct" // Initialize components for Routine "instruct"
instructClock = new util.Clock(); instructClock = new util.Clock();
ready = new core.Keyboard({psychoJS: psychoJS, clock: new util.Clock(), waitForStart: true}); ready = new core.Keyboard({psychoJS: psychoJS, clock: new util.Clock(), waitForStart: true});
psychoJS.window.backgroundImage = "toxen"; psychoJS.window.backgroundImage = "starformation.jpg";
// Initialize components for Routine "gabor" // Initialize components for Routine "gabor"
gaborClock = new util.Clock(); gaborClock = new util.Clock();