use ui;
use ui:s3d;
use core:io;
use core:geometry;
use graphics;
use lang:bs:macro;

/**
 * Vertex type used for output from the pixel shader.
 *
 * Just as for the output from the vertex shader, the system has some expectations about the output
 * format. Namely, the system expects zero or more values that are "color" or "output" (they are
 * synonymous). These are mapped to the different output layers of the Graphics object (the first is
 * the color buffer by default).
 *
 * Additionally, a single float may be marked as "depth", which lets the shader modify the depth
 * value as desired. All other outputs are ignored.
 */
vertex Output {
	// Pixel color.
	Color color : color;
}

// Get a resource. Checks that the file exists.
Url resUrl(Str filename) {
	if (url = named{res}.url) {
		Url f = url / filename;
		if (f.exists)
			return f;
	}
	if (url = named{:res}.url) {
		Url f = url / filename;
		if (f.exists)
			return f;
	}
	throw InternalError("The file ${filename} was not found.");
}


/**
 * Main window shared between all samples.
 */
frame SampleWindow {
	init(Str title, Painter3D painter) {
		init(title, Size(500, 500)) {}

		this.painter = painter;

		create();
	}
}

/**
 * Subclass of the 3D painter with some additional functionality.
 */
class SamplePainter3D extends Painter3D {
	// Start time.
	Moment start;

	// Create.
	init() {
		init {}
	}

	// Compute the current animation time for some animation.
	// The returned `Float` will increase from 0.0 to 1.0 in cycles of `cycle`.
	// This is intended to make it easier to implement simple repeating animations.
	Float animationTime(Duration cycle) {
		Moment now;
		while (now - start > cycle) {
			start += cycle;
		}
		return (now - start) / cycle;
	}
}

void runSample(Str title, Painter3D painter) on Ui {
	SampleWindow(title, painter).waitForClose();
}
