Collection of useful utilities for Java games and apps. A lot of interesting utilities that could maybe still find some use if you work with Java...
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mightyutils/doc/math-constraints.md

4.3 KiB

Dynamic constraints - DynMath library

DynMath is a library aimed at making GUI positioning and sizing easier.

It allows you to compose numeric, vector and rectangle constraints for the GUI elements, and when some of the input values changes (such as window size), all the constraints will reflect this change.

For example:

// a Rect representing the whole window
Rect window = new Rect() {
	
	@Override
	public Vect size()
	{
		return /* actual window size */;
	}
	
	@Override
	public Vect origin()
	{
		return Vect.ZERO;
	}
};

// navbar in the bottom 20% of the window
Rect navbar = window.bottomEdge().growUp(window.height().perc(20));

// now whenever the window is resized, navbar will have the right size

The library is, however, very general-purpose, and has many other uses besides the GUI positioning.

What is available

Short answer: A LOT!

Long answer:

Constraint Types

There are three kinds of "constraints":

  • Num - a number (or a 1D vector)
  • Vect - 2D or 3D vector, can be used as absolute or relative coordinate
  • Rect - a 2D rectangle composed of origin and size Vect

Each of them has a bunch of different variants, and can also be further extended to suit your needs. For example, you could make Gui components extend AbstractRectCache or something like that.

Generally, all the constraints are immutable (except the mutable variants, such as VectVar.

Making Constraints

Each Vect, Rect and Num have a lot of factory methods (.make(), .makeVar() etc, with various argument types) to cover all the most common scenarios. If none of those is what you want, you can just make a new instance of the respective constraint, and make it fit your needs.

Variants of Constraints

Just Num, Vect and Rect would be boring.

Each of them has (at least) the following variants (it'll be shown on Vect):

  • Vect - the basic abstract type. Can be extended to make dynamic variables (override the .x(), .y() (and optionally .z()) methods with your own calculations). Vect is generally dynamic, thus doing math on Vect will give you "view" of the result, which changes as the original Vect changes.

    Note, that Vect uses .x(), .y() and .z(), Rect uses .origin() and .size(), and Num uses .value(). Each variant of the constraints overrides those methods in a different way.

  • VectConst - concrete implementation of Vect, backed by actual numbers. As the name suggests, it is immutable and keeps the same value. You can obtain a const from ie. Vect by calling it's .freeze() method.

  • VectVar - like const, it is backed by actual numbers, but they are not final and it has setters to change their values. This could be used as a input for computation.

  • VectAdapter - kinda like a proxy with abstract method to provide the proxied Vect.

  • VectProxy - implementation of VectAdapter, that keeps the proxied constraint in a variable and this can be changed using the .setVect() method.

  • VectCache (and AbstractVectCache) - useful if you have a very complex calculation and don't want it all to be evaluated each time you want the result. Simply call the .cached() result on your formula, and store it into a VectCache variable. Each time you call it's .poll() method, it will copy current value into an internal VectVar (see, that is what they're good for), and this is then used to get the result.

  • VectBound - okay, this is not really a variant. It is an interface for anything that can has a Vect value. You can use VectBoundAdapter to make an actual Vect out of it.

Digests

If you use some constraint often, like VERY often, ie. for OpenGL rendering each frame, it's a good idea to use digests. The important part is that the digest is cached until the value changes, so it's very efficient if you need the digest often.

All of the constraints support taking digests.

Steps to enable and use digest caching:

  1. Call .enableDigestCaching(true) on your constraint to turn on the feature (cache does this by default)
  2. Each time you need a digest, call the .digest() method on your constraint.
  3. Each time the value is expected to have changed, call .markDigestDirty() on it, and the digest will be rebuilt next time it is needed. Cache does this on each .poll() automatically for you.