Skip to content

Commit

Permalink
custom lightbeam scroll field + fix alpha fade
Browse files Browse the repository at this point in the history
  • Loading branch information
earthwise01 committed Jan 13, 2025
1 parent 835b78a commit be2b4a0
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 14 deletions.
18 changes: 13 additions & 5 deletions Loenn/entities/custom_lightbeam.lua
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ lightBeam.placements = {
singleColor = false,
fadeWhenNear = true,
fadeOnTransition = true,
flagFadeTime = 0.25
flagFadeTime = 0.25,
scroll = 1.0,
scrollAnchor = "0, 0"
}
},
{
Expand Down Expand Up @@ -64,7 +66,9 @@ lightBeam.placements = {
singleColor = false,
fadeWhenNear = true,
fadeOnTransition = true,
flagFadeTime = 0.25
flagFadeTime = 0.25,
scroll = 1.0,
scrollAnchor = "0, 0"
}
},
}
Expand Down Expand Up @@ -93,20 +97,24 @@ lightBeam.fieldInformation = {
fieldType = "integer",
options = depths.addDepth(depths.getDepths(), "Lightbeams", -9998),
editable = true
}
},
-- wip
-- scrollAnchor = {
-- fieldType = "sorbetHelper.vector",
-- }
}

-- hide rainbow specific fields unless rainbow is enabled and vice versa
function lightBeam.fieldOrder(entity)
local fields = {}
if entity.rainbow == true and entity.useCustomRainbowColors == true then
fields = {
"x", "y", "width", "height", "colors", "centerX", "gradientSize", "centerY", "gradientSpeed", "alpha", "depth", "rotation", "flag", "flagFadeTime", "texture",
"x", "y", "width", "height", "colors", "centerX", "gradientSize", "centerY", "gradientSpeed", "alpha", "depth", "rotation", "scroll", "scrollAnchor", "flag", "flagFadeTime", "texture",
"inverted", "fadeOnTransition", "rainbow", "useCustomRainbowColors", "noParticles", "fadeWhenNear", "singleColor", "loopColors"
}
else
fields = {
"x", "y", "width", "height", "color", "alpha", "depth", "rotation", "flag", "flagFadeTime", "texture",
"x", "y", "width", "height", "color", "alpha", "depth", "rotation", "scroll", "scrollAnchor", "flag", "flagFadeTime", "texture",
"inverted", "fadeOnTransition", "rainbow", "useCustomRainbowColors", "noParticles", "fadeWhenNear", "singleColor"
}
end
Expand Down
2 changes: 2 additions & 0 deletions Loenn/lang/en_gb.lang
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ entities.SorbetHelper/CustomLightbeam.attributes.name.singleColor=Uniform Rainbo
entities.SorbetHelper/CustomLightbeam.attributes.description.singleColor=Determines whether the rainbow lightbeam is the same color throughout or uses a gradient across all the beams of light.\n(Requires rainbow to be checked)
entities.SorbetHelper/CustomLightbeam.attributes.description.fadeWhenNear=Determines whether the lightbeam fades out when the player is close to it.
entities.SorbetHelper/CustomLightbeam.attributes.description.fadeOnTransition=Determines whether the lightbeam fades out during screen transitions.
entities.SorbetHelper/CustomLightbeam.attributes.description.scroll=meow
entities.SorbetHelper/CustomLightbeam.attributes.description.scrollAnchor=the parallax scroll anchor, relative to the lightbeam

# Winged Strawberry Direction Controller
entities.SorbetHelper/WingedStrawberryDirectionController.placements.name.wingedStrawberryController=Winged Strawberry Direction Controller
Expand Down
4 changes: 4 additions & 0 deletions Loenn/lang/en_gb.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,10 @@ Entities:
Description: Determines whether the lightbeam fades out when the player is close to it.
fadeOnTransition:
Description: Determines whether the lightbeam fades out during screen transitions.
scroll:
Description: meow
scrollAnchor:
Description: the parallax scroll anchor, relative to the lightbeam

SorbetHelper/WingedStrawberryDirectionController:
Placements:
Expand Down
72 changes: 63 additions & 9 deletions Source/Entities/CustomLightBeam.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using Monocle;
using Celeste.Mod.Entities;
using Celeste.Mod.SorbetHelper.Utils;
using System.Globalization;
using System.Linq;

namespace Celeste.Mod.SorbetHelper.Entities {

Expand Down Expand Up @@ -38,6 +40,20 @@ public class CustomLightBeam : Entity {

private readonly bool noParticles;

private readonly float Scroll;
private Vector2 ScrollAnchor;
private Vector2 RenderPosition {
get {
// edge case so normal lightbeams dont need to bother with anything
if (Scroll == 1f)
return Position;

// hopefully i mathed right and this actually fully does what i think it does
var cam = (Scene as Level).Camera.GetCenter();
return cam + (Position - ScrollAnchor * (1f - Scroll) - cam * Scroll);
}
}

private float baseAlpha = 1;
private float flagAlpha = 1;
private float alpha;
Expand Down Expand Up @@ -75,6 +91,17 @@ public CustomLightBeam(EntityData data, Vector2 offset) : base(data.Position + o
fadeWhenNear = data.Bool("fadeWhenNear", true);
fadeOnTransition = data.Bool("fadeOnTransition", true);

// eh
Scroll = data.Float("scroll", 1f);
ScrollAnchor = new Vector2(0f, 0f);
var a = data.Attr("scrollAnchor", "0, 0").Split(',', StringSplitOptions.TrimEntries);
if (a.Length >= 1)
float.TryParse(a[0], null, out ScrollAnchor.X);
if (a.Length >= 2)
float.TryParse(a[1], null, out ScrollAnchor.Y);
ScrollAnchor += Position;
//ScrollAnchor = Position + new Vector2(data.Float("scrollAnchorX"), data.Float("scrollAnchorY"));

float alpha = Math.Clamp(data.Float("alpha", 1f), 0f, 1f);

beamTexture = GFX.Game[data.Attr("texture", "util/lightbeam")];
Expand All @@ -101,8 +128,8 @@ public CustomLightBeam(EntityData data, Vector2 offset) : base(data.Position + o

// offscreen culling stuff
// kinda janky i think but it works
Vector2 baseCornerA = Position - Calc.AngleToVector(rotation, 1f) * (lightWidth / 2f); // would be top left with a rotation of 0f
Vector2 baseCornerB = Position + Calc.AngleToVector(rotation, 1f) * (lightWidth / 2); // would be top right with a rotation of 0f
Vector2 baseCornerA = -Calc.AngleToVector(rotation, 1f) * (lightWidth / 2f); // would be top left with a rotation of 0f
Vector2 baseCornerB = Calc.AngleToVector(rotation, 1f) * (lightWidth / 2); // would be top right with a rotation of 0f
Vector2 edgeCornerA = baseCornerA + Calc.AngleToVector(rotation + (float)Math.PI / 2f, 1f) * lightLength; // would be bottom left with a rotation of 0f
Vector2 edgeCornerB = baseCornerB + Calc.AngleToVector(rotation + (float)Math.PI / 2f, 1f) * lightLength; // would be bottom right with a rotation of 0f

Expand All @@ -129,14 +156,14 @@ public override void Awake(Scene scene) {
baseAlpha = 0f;
}

// initialize render target and matrix
if (!useRenderTarget)
return;

// initialize render target and matrix
// whY did i do this huhh?? what was i thinking
lightbeamTarget ??= VirtualContent.CreateRenderTarget("sorbet-custom-lightbeam", (int)(rectangleRight - rectangleLeft + visibilityPadding), (int)(rectangleBottom - rectangleTop + visibilityPadding));
Vector2 offset = Calc.AngleToVector(rotation - (float)Math.PI / 2f, lightLength) / 2f;
targetMatrix = Matrix.CreateTranslation(-Position.X + lightbeamTarget.Width / 2f, -Position.Y + lightbeamTarget.Height / 2f, 0f) * Matrix.CreateTranslation(offset.X, offset.Y, 0f);
targetMatrix = Matrix.CreateTranslation(lightbeamTarget.Width / 2f, lightbeamTarget.Height / 2f, 0f) * Matrix.CreateTranslation(offset.X, offset.Y, 0f);
RenderToTarget();
}

Expand All @@ -161,6 +188,9 @@ public override void Update() {
Level level = Scene as Level;
Player entity = Scene.Tracker.GetEntity<Player>();

var pos = Position;
Position = RenderPosition;

wasVisibleOnCamera = Visible;
Visible = InView(level.Camera);

Expand Down Expand Up @@ -202,10 +232,13 @@ public override void Update() {
float num = Calc.Random.Next(lightWidth - 4) + 2 - lightWidth / 2;
position += num * vector3.Perpendicular();
// if rainbow is enabled and rainbowSingleColor is disabled, call GetHue for the particle's color, otherwise use the color variable.
// doesn't track properly with parallax but idk
level.Particles.Emit(LightBeam.P_Glow, position, (rainbow && !rainbowSingleColor) ? GetHue(position) : color, rotation + (float)Math.PI / 2f);
}

base.Update();

Position = pos;
}

/* public override void DebugRender(Camera camera) {
Expand Down Expand Up @@ -233,21 +266,37 @@ public void BeforeRender() {

public override void Render() {
if (alpha > 0f) {
var pos = Position;
Position = RenderPosition;

if (useRenderTarget)
Draw.SpriteBatch.Draw(lightbeamTarget, new Vector2(rectangleLeft - visibilityPadding / 2, rectangleTop - visibilityPadding / 2), null, Color.White * alpha, 0f, Vector2.Zero, 1f, SpriteEffects.None, 0f);
Draw.SpriteBatch.Draw(lightbeamTarget, Position + new Vector2(rectangleLeft - visibilityPadding / 2, rectangleTop - visibilityPadding / 2), null, Color.White * alpha, 0f, Vector2.Zero, 1f, SpriteEffects.None, 0f);
else
RenderLightbeam();

Position = pos;
}
}

private void RenderToTarget() {
Engine.Graphics.GraphicsDevice.SetRenderTarget(lightbeamTarget);
Engine.Graphics.GraphicsDevice.Clear(Color.Transparent);

Draw.SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointWrap, DepthStencilState.None, RasterizerState.CullNone, null, targetMatrix);
var pos = Position;
var renderPos = RenderPosition;

var matrix = targetMatrix * Matrix.CreateTranslation(new Vector3(-renderPos.X, -renderPos.Y, 0f));
Draw.SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointWrap, DepthStencilState.None, RasterizerState.CullNone, null, matrix);

Position = renderPos;
var a = alpha;
alpha = 1f;

RenderLightbeam();

alpha = a;
Position = pos;

Draw.SpriteBatch.End();
}

Expand Down Expand Up @@ -278,7 +327,7 @@ private void RenderLightbeam() {
private void DrawBeam(float offset, float width, float length, float a) {
float beamRotation = rotation + (float)Math.PI / 2f;
// if rainbow is enabled and rainbowSingleColor is disabled, call GetHue for the beam's color, otherwise use the color variable.
Color beamColor = ((rainbow && !rainbowSingleColor) ? GetHue(Position + Calc.AngleToVector(rotation, 1f) * offset) : color) * a;
Color beamColor = ((rainbow && !rainbowSingleColor) ? GetHue(Position + Calc.AngleToVector(rotation, 1f) * offset) : color) * a * alpha;

if (width >= 1f) {
beamTexture.Draw(Position + Calc.AngleToVector(rotation, 1f) * offset, new Vector2(0f, 0.5f), beamColor, new Vector2(1f / beamTexture.Width * length, width), beamRotation);
Expand Down Expand Up @@ -315,7 +364,12 @@ private Color GetHue(Vector2 position) {
return Color.Lerp(rainbowColors[colorIndex], rainbowColors[colorIndex + 1], progressInIndex);
}

private bool InView(Camera camera) =>
rectangleLeft < camera.Right + visibilityPadding && rectangleRight > camera.Left - visibilityPadding && rectangleTop < camera.Bottom + visibilityPadding && rectangleBottom > camera.Top - visibilityPadding;
private bool InView(Camera camera) {
var pos = Position;
if (pos.X + rectangleRight > camera.X - visibilityPadding && pos.X + rectangleLeft < camera.X + camera.Viewport.Width + visibilityPadding)
return pos.Y + rectangleBottom > camera.Y - visibilityPadding && pos.Y + rectangleTop < camera.Y + camera.Viewport.Height + visibilityPadding;

return false;
}
}
}

0 comments on commit be2b4a0

Please sign in to comment.