mirror of
https://gitlab.com/AutumnMeowMeow/jexer
synced 2024-09-19 11:50:19 -06:00
Window plasma fade-in
This commit is contained in:
parent
a229c8cbd0
commit
0053d9347f
6 changed files with 248 additions and 15 deletions
|
@ -52,6 +52,7 @@ import jexer.bits.Clipboard;
|
||||||
import jexer.bits.ColorTheme;
|
import jexer.bits.ColorTheme;
|
||||||
import jexer.bits.StringUtils;
|
import jexer.bits.StringUtils;
|
||||||
import jexer.effect.Effect;
|
import jexer.effect.Effect;
|
||||||
|
import jexer.effect.WindowBurnInEffect;
|
||||||
import jexer.effect.WindowFadeInEffect;
|
import jexer.effect.WindowFadeInEffect;
|
||||||
import jexer.effect.WindowFadeOutEffect;
|
import jexer.effect.WindowFadeOutEffect;
|
||||||
import jexer.event.TCommandEvent;
|
import jexer.event.TCommandEvent;
|
||||||
|
@ -3443,13 +3444,20 @@ public class TApplication implements Runnable {
|
||||||
desktop.setActive(false);
|
desktop.setActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the window has an open effect, kick that off.
|
if (!window.disableOpenEffect()) {
|
||||||
String windowOpenEffect = System.getProperty("jexer.effect.windowOpen",
|
// If the window has an open effect, kick that off.
|
||||||
"none").toLowerCase();
|
String windowOpenEffect = System.getProperty(
|
||||||
|
"jexer.effect.windowOpen", "none").toLowerCase();
|
||||||
|
|
||||||
if (windowOpenEffect.equals("fade")) {
|
if (windowOpenEffect.equals("fade")) {
|
||||||
synchronized (effects) {
|
synchronized (effects) {
|
||||||
effects.add(new WindowFadeInEffect(window));
|
effects.add(new WindowFadeInEffect(window));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (windowOpenEffect.equals("burn")) {
|
||||||
|
synchronized (effects) {
|
||||||
|
effects.add(new WindowBurnInEffect(window));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1553,15 +1553,20 @@ public abstract class TWidget implements Comparable<TWidget> {
|
||||||
// The TWindow overlay has to be here so that it can cover drawn
|
// The TWindow overlay has to be here so that it can cover drawn
|
||||||
// widgets.
|
// widgets.
|
||||||
if (this instanceof TWindow) {
|
if (this instanceof TWindow) {
|
||||||
|
screen.setClipRight(overlayClipRight);
|
||||||
|
screen.setClipBottom(overlayClipBottom);
|
||||||
|
screen.setOffsetX(overlayOffsetX);
|
||||||
|
screen.setOffsetY(overlayOffsetY);
|
||||||
|
|
||||||
|
// Let the overlay draw.
|
||||||
Tackboard overlay = ((TWindow) this).overlay;
|
Tackboard overlay = ((TWindow) this).overlay;
|
||||||
if (overlay != null) {
|
if (overlay != null) {
|
||||||
screen.setClipRight(overlayClipRight);
|
|
||||||
screen.setClipBottom(overlayClipBottom);
|
|
||||||
screen.setOffsetX(overlayOffsetX);
|
|
||||||
screen.setOffsetY(overlayOffsetY);
|
|
||||||
overlay.draw(getScreen(),
|
overlay.draw(getScreen(),
|
||||||
getApplication().getBackend().isImagesOverText());
|
getApplication().getBackend().isImagesOverText());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now let a custom window effect draw.
|
||||||
|
((TWindow) this).onPostDraw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1081,6 +1081,15 @@ public class TWindow extends TWidget {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called immediately after the windo is drawn. This can be
|
||||||
|
* used by subclasses of TWindow to alter the final post-rendered window
|
||||||
|
* screen area.
|
||||||
|
*/
|
||||||
|
protected void onPostDraw() {
|
||||||
|
// Default does nothing
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// TWindow ----------------------------------------------------------------
|
// TWindow ----------------------------------------------------------------
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -1865,6 +1874,17 @@ public class TWindow extends TWidget {
|
||||||
return alpha;
|
return alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true, disable any window opening effect. This is used by the
|
||||||
|
* window closing effects themselves so that they are not themselves
|
||||||
|
* opened.
|
||||||
|
*
|
||||||
|
* @return true if the window open effect should be disabled
|
||||||
|
*/
|
||||||
|
public boolean disableOpenEffect() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true, disable any window closing effect. This is used by the
|
* If true, disable any window closing effect. This is used by the
|
||||||
* window closing effects themselves so that they can be closed when
|
* window closing effects themselves so that they can be closed when
|
||||||
|
|
197
src/jexer/effect/WindowBurnInEffect.java
Normal file
197
src/jexer/effect/WindowBurnInEffect.java
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
/*
|
||||||
|
* Jexer - Java Text User Interface
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Autumn Lamonte
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author Autumn Lamonte ⚧ Trans Liberation Now
|
||||||
|
* @version 1
|
||||||
|
*/
|
||||||
|
package jexer.effect;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
|
import jexer.TApplication;
|
||||||
|
import jexer.TWindow;
|
||||||
|
import jexer.backend.Screen;
|
||||||
|
import jexer.event.TInputEvent;
|
||||||
|
import jexer.tackboard.Bitmap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make the window look like it was was burned in with plasma fire.
|
||||||
|
*/
|
||||||
|
public class WindowBurnInEffect implements Effect {
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Constants --------------------------------------------------------------
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Variables --------------------------------------------------------------
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The window to burn in.
|
||||||
|
*/
|
||||||
|
private TWindow window;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fake window with the plasma effect.
|
||||||
|
*/
|
||||||
|
private TWindow fakeWindow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The bitmap for the plasma effect.
|
||||||
|
*/
|
||||||
|
private Bitmap plasma;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The burn alpha.
|
||||||
|
*/
|
||||||
|
private int alpha = 0;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Constructors -----------------------------------------------------------
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public contructor.
|
||||||
|
*
|
||||||
|
* @param window the window to burn in
|
||||||
|
*/
|
||||||
|
public WindowBurnInEffect(final TWindow window) {
|
||||||
|
this.window = window;
|
||||||
|
|
||||||
|
alpha = 220;
|
||||||
|
|
||||||
|
final int x = window.getX();
|
||||||
|
final int y = window.getY();
|
||||||
|
final TApplication app = window.getApplication();
|
||||||
|
|
||||||
|
app.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
if (app.isModalThreadRunning()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fakeWindow = new TWindow(window.getApplication(), "",
|
||||||
|
window.getX(), window.getY(),
|
||||||
|
window.getWidth(), window.getHeight(),
|
||||||
|
TWindow.MODAL) {
|
||||||
|
|
||||||
|
// Disable all inputs.
|
||||||
|
@Override
|
||||||
|
public void handleEvent(final TInputEvent event) {
|
||||||
|
// NOP
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw() {
|
||||||
|
// Draw nothing. TWidget.drawChildren() will draw
|
||||||
|
// the overlay, which contains the plasma.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean disableOpenEffect() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean disableCloseEffect() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fakeWindow.setX(x);
|
||||||
|
fakeWindow.setY(y);
|
||||||
|
fakeWindow.setAlpha(alpha);
|
||||||
|
|
||||||
|
// Generate the plasma.
|
||||||
|
Screen screen = fakeWindow.getScreen();
|
||||||
|
int width = fakeWindow.getWidth() * screen.getTextWidth();
|
||||||
|
int height = fakeWindow.getHeight() * screen.getTextHeight();
|
||||||
|
BufferedImage burn = new BufferedImage(width, height,
|
||||||
|
BufferedImage.TYPE_INT_ARGB);
|
||||||
|
|
||||||
|
// https://lodev.org/cgtutor/plasma.html has the general
|
||||||
|
// idea. I just played around and it's alright for a start.
|
||||||
|
int w = width;
|
||||||
|
int h = height;
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
int red = (int) (128.0 + 2 * (Math.sin((x + y) / 2.0) +
|
||||||
|
Math.sin(x * x + y)) * 128.0);
|
||||||
|
int green = (int) (128.0 + (Math.sin(y / 7.0) +
|
||||||
|
Math.cos(Math.log(y * y / 6))) * 128.0);
|
||||||
|
int blue = (int) (128.0 + Math.cos(Math.sqrt(x * x + y * y) / 3.0) * 128.0);
|
||||||
|
red = Math.max(0, Math.min(red, 255));
|
||||||
|
green = Math.max(0, Math.min(green, 255));
|
||||||
|
blue = Math.max(0, Math.min(blue, 255));
|
||||||
|
int rgb = ( 0xFF << 24)
|
||||||
|
| ( red << 16)
|
||||||
|
| (green << 8)
|
||||||
|
| blue;
|
||||||
|
burn.setRGB(x, y, rgb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plasma = new Bitmap(0, 0, 0, burn);
|
||||||
|
|
||||||
|
fakeWindow.addOverlay(plasma);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Effect -----------------------------------------------------------------
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the effect.
|
||||||
|
*/
|
||||||
|
public void update() {
|
||||||
|
if (fakeWindow == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (alpha > 0) {
|
||||||
|
// Aiming for 1/8 second, at 32 FPS = 4 frames. 256 / 4 = 64.
|
||||||
|
alpha = Math.max(alpha - 96, 0);
|
||||||
|
fakeWindow.setAlpha(alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true, the effect is completed and can be removed.
|
||||||
|
*
|
||||||
|
* @return true if this effect is finished
|
||||||
|
*/
|
||||||
|
public boolean isCompleted() {
|
||||||
|
if (alpha == 0) {
|
||||||
|
if (fakeWindow != null) {
|
||||||
|
fakeWindow.close();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -31,8 +31,7 @@ package jexer.effect;
|
||||||
import jexer.TWindow;
|
import jexer.TWindow;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A desktop or window effect does a blingy transformation before the screen
|
* Make the window fade in.
|
||||||
* is sent to the device.
|
|
||||||
*/
|
*/
|
||||||
public class WindowFadeInEffect implements Effect {
|
public class WindowFadeInEffect implements Effect {
|
||||||
|
|
||||||
|
|
|
@ -33,8 +33,7 @@ import jexer.backend.Screen;
|
||||||
import jexer.event.TInputEvent;
|
import jexer.event.TInputEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A desktop or window effect does a blingy transformation before the screen
|
* Make the window fade out.
|
||||||
* is sent to the device.
|
|
||||||
*/
|
*/
|
||||||
public class WindowFadeOutEffect implements Effect {
|
public class WindowFadeOutEffect implements Effect {
|
||||||
|
|
||||||
|
@ -68,7 +67,7 @@ public class WindowFadeOutEffect implements Effect {
|
||||||
/**
|
/**
|
||||||
* Public contructor.
|
* Public contructor.
|
||||||
*
|
*
|
||||||
* @param window the window to fade in
|
* @param window the window to fade out
|
||||||
*/
|
*/
|
||||||
public WindowFadeOutEffect(final TWindow window) {
|
public WindowFadeOutEffect(final TWindow window) {
|
||||||
final Screen oldScreen = window.getScreen().snapshotPhysical(
|
final Screen oldScreen = window.getScreen().snapshotPhysical(
|
||||||
|
@ -103,6 +102,11 @@ public class WindowFadeOutEffect implements Effect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean disableOpenEffect() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean disableCloseEffect() {
|
public boolean disableCloseEffect() {
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in a new issue