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 {boolean} [options.fullscr= false] whether or not to go fullscreen
* @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.contrast= 1] sets the contrast value
* @param {string} [options.units= 'pix'] the units of the window
@ -71,6 +73,8 @@ export class Window extends PsychObject
name,
fullscr = false,
color = new Color("black"),
backgroundImage = "",
backgroundFit = "cover",
gamma = 1,
contrast = 1,
units = "pix",
@ -93,11 +97,7 @@ export class Window extends PsychObject
this._drawList = [];
this._addAttribute("fullscr", fullscr);
this._addAttribute("color", color, new Color("black"), () => {
if (this._backgroundSprite) {
this._backgroundSprite.tint = this._color.int;
}
});
this._addAttribute("color", color, new Color("black"));
this._addAttribute("gamma", gamma, 1, () => {
this._adjustmentFilter.gamma = this._gamma;
});
@ -108,6 +108,8 @@ export class Window extends PsychObject
this._addAttribute("waitBlanking", waitBlanking);
this._addAttribute("autoLog", autoLog);
this._addAttribute("size", []);
this._addAttribute("backgroundImage", backgroundImage, "");
this._addAttribute("backgroundFit", backgroundFit, "cover");
// setup PIXI:
this._setupPixi();
@ -139,6 +141,12 @@ export class Window extends PsychObject
}
}
static BACKGROUND_FIT_ENUM = {
cover: 0,
contain: 1,
auto: 2
};
/**
* Close the window.
*
@ -360,6 +368,134 @@ export class Window extends PsychObject
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.
*
@ -372,7 +508,7 @@ export class Window extends PsychObject
if (this._renderer)
{
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
@ -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
// won't get affected.
this._backgroundSprite = new PIXI.Sprite(PIXI.Texture.WHITE);
this._backgroundSprite.scale.y = -1;
this._backgroundSprite.tint = this.color.int;
this._backgroundSprite.width = this._size[0];
this._backgroundSprite.height = this._size[1];
@ -588,8 +725,15 @@ export class Window extends PsychObject
}
Window._resizePixiRenderer(this, e);
if (this._backgroundImage === undefined)
{
this._backgroundSprite.width = this._size[0];
this._backgroundSprite.height = this._size[1];
}
else
{
this.backgroundFit = this._backgroundFit;
}
this._fullRefresh();
};
window.addEventListener("resize", this._resizeCallback);

View File

@ -67,6 +67,10 @@ psychoJS.start({
expInfo: expInfo,
configURL: "../config.json",
resources: [
{
name: "starformation.jpg",
path: "./test_resources/starformation.jpg"
},
{
name: "cool.gif",
path: "./test_resources/cool.gif"
@ -132,7 +136,7 @@ async function experimentInit() {
// Initialize components for Routine "instruct"
instructClock = new util.Clock();
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"
gaborClock = new util.Clock();