marble select

This commit is contained in:
RandomityGuy 2022-11-24 18:41:24 +05:30
parent eb8978b406
commit ef9a7cbe5e
8 changed files with 372 additions and 62 deletions

View file

@ -1,5 +1,6 @@
package src;
import dts.TSDrawPrimitive;
import hxd.res.Sound;
import h3d.col.Bounds;
import src.TimeState;
@ -563,38 +564,87 @@ class DtsObject extends GameObject {
indices: []
});
for (primitive in dtsMesh.primitives) {
var k = 0;
var geometrydata = materialGeometry[primitive.matIndex];
for (i in primitive.firstElement...(primitive.firstElement + primitive.numElements - 2)) {
var i1 = dtsMesh.indices[i];
var i2 = dtsMesh.indices[i + 1];
var i3 = dtsMesh.indices[i + 2];
if (k % 2 == 0) {
// Swap the first and last index to mainting correct winding order
var ab = new Vector();
var ac = new Vector();
function addTriangleFromIndices(i1:Int, i2:Int, i3:Int, materialIndex:Int) {
ab.set(vertices[i2].x - vertices[i1].x, vertices[i2].y - vertices[i1].y, vertices[i2].z - vertices[i1].z);
ac.set(vertices[i3].x - vertices[i1].x, vertices[i3].y - vertices[i1].y, vertices[i3].z - vertices[i1].z);
var normal = ab.cross(ac);
normal.normalize();
var dot1 = normal.dot(vertexNormals[i1]);
var dot2 = normal.dot(vertexNormals[i2]);
var dot3 = normal.dot(vertexNormals[i3]);
if (!StringTools.contains(this.dtsPath, 'helicopter.dts') && !StringTools.contains(this.dtsPath, 'tornado.dts'))
if (dot1 < 0 && dot2 < 0 && dot3 < 0) {
var temp = i1;
i1 = i3;
i3 = temp;
}
// ^ temp hardcoded fix
for (index in [i3, i2, i1]) {
var vertex = vertices[index];
geometrydata.vertices.push(new Vector(vertex.x, vertex.y, vertex.z));
var geometrydata = materialGeometry[materialIndex];
var uv = dtsMesh.uv[index];
geometrydata.uvs.push(new UV(uv.x, uv.y));
for (index in [i3, i2, i1]) {
var vertex = vertices[index];
geometrydata.vertices.push(new Vector(vertex.x, vertex.y, vertex.z));
var normal = vertexNormals[index];
geometrydata.normals.push(new Vector(normal.x, normal.y, normal.z));
var uv = dtsMesh.uv[index];
geometrydata.uvs.push(new UV(uv.x, uv.y));
var normal = vertexNormals[index];
geometrydata.normals.push(new Vector(normal.x, normal.y, normal.z));
}
geometrydata.indices.push(i1);
geometrydata.indices.push(i2);
geometrydata.indices.push(i3);
}
for (primitive in dtsMesh.primitives) {
var materialIndex = primitive.matIndex & TSDrawPrimitive.MaterialMask;
var drawType = primitive.matIndex & TSDrawPrimitive.TypeMask;
var geometrydata = materialGeometry[materialIndex];
if (drawType == TSDrawPrimitive.Triangles) {
var i = primitive.firstElement;
while (i < primitive.firstElement + primitive.numElements) {
var i1 = dtsMesh.indices[i];
var i2 = dtsMesh.indices[i + 1];
var i3 = dtsMesh.indices[i + 2];
addTriangleFromIndices(i1, i2, i3, materialIndex);
i += 3;
}
} else if (drawType == TSDrawPrimitive.Strip) {
var k = 0;
for (i in primitive.firstElement...(primitive.firstElement + primitive.numElements - 2)) {
var i1 = dtsMesh.indices[i];
var i2 = dtsMesh.indices[i + 1];
var i3 = dtsMesh.indices[i + 2];
geometrydata.indices.push(i1);
geometrydata.indices.push(i2);
geometrydata.indices.push(i3);
if (k % 2 == 0) {
// Swap the first and last index to mainting correct winding order
var temp = i1;
i1 = i3;
i3 = temp;
}
k++;
addTriangleFromIndices(i1, i2, i3, materialIndex);
k++;
}
} else if (drawType == TSDrawPrimitive.Fan) {
var i = primitive.firstElement;
while (i < primitive.firstElement + primitive.numElements - 2) {
var i1 = dtsMesh.indices[primitive.firstElement];
var i2 = dtsMesh.indices[i + 1];
var i3 = dtsMesh.indices[i + 2];
addTriangleFromIndices(i1, i2, i3, materialIndex);
i++;
}
}
}
@ -918,18 +968,20 @@ class DtsObject extends GameObject {
if (!this.useInstancing) {
for (material in this.materials) {
if (this.currentOpacity != 1) {
// material.blendMode = BlendMode.Alpha;
// if (this.alphaShader == null) {
// this.alphaShader = new AlphaMult();
// }
// if (material.mainPass.getShader(AlphaMult) == null) {
// material.mainPass.addShader(this.alphaShader);
// }
// this.alphaShader.alpha = this.currentOpacity;
// } else {
// if (alphaShader != null) {
// alphaShader.alpha = this.currentOpacity;
// }
material.blendMode = BlendMode.Alpha;
if (this.alphaShader == null) {
this.alphaShader = new AlphaMult();
}
if (material.mainPass.getShader(AlphaMult) == null) {
material.mainPass.addShader(this.alphaShader);
}
this.alphaShader.alpha = this.currentOpacity;
} else {
if (alphaShader != null) {
material.blendMode = BlendMode.None;
alphaShader.alpha = this.currentOpacity;
material.mainPass.removeShader(alphaShader);
}
}
}
}

View file

@ -1,5 +1,6 @@
package src;
import h3d.mat.MaterialDatabase;
import shaders.MarbleReflection;
import shaders.CubemapRenderer;
import h3d.shader.AlphaMult;
@ -206,8 +207,6 @@ class Marble extends GameObject {
this.omega = new Vector();
this.camera = new CameraController(cast this);
this.collider = new SphereCollisionEntity(cast this);
this.bounceEmitterData = new ParticleData();
this.bounceEmitterData.identifier = "MarbleBounceParticle";
this.bounceEmitterData.texture = ResourceLoader.getResource("data/particles/star.png", ResourceLoader.getTexture, this.textureResources);
@ -236,23 +235,50 @@ class Marble extends GameObject {
public function init(level:MarbleWorld, onFinish:Void->Void) {
this.level = level;
var geom = Sphere.defaultUnitSphere();
geom.addUVs();
var marbleTexture = ResourceLoader.getFileEntry("data/shapes/balls/base.marble.png").toTexture();
var marbleMaterial = Material.create(marbleTexture);
marbleMaterial.shadows = false;
marbleMaterial.castShadows = true;
var marbleDts = new DtsObject();
marbleDts.dtsPath = Settings.optionsSettings.marbleModel;
marbleDts.matNameOverride.set("base.marble", Settings.optionsSettings.marbleSkin + ".marble");
marbleDts.showSequences = false;
marbleDts.useInstancing = false;
marbleDts.init(null, () -> {}); // SYNC
for (mat in marbleDts.materials) {
mat.castShadows = true;
mat.shadows = true;
mat.receiveShadows = false;
// mat.mainPass.culling = None;
if (Settings.optionsSettings.reflectiveMarble) {
this.cubemapRenderer = new CubemapRenderer(level.scene);
mat.mainPass.addShader(new MarbleReflection(this.cubemapRenderer.cubemap));
}
}
// Calculate radius according to marble model (egh)
var b = marbleDts.getBounds();
var avgRadius = (b.xSize + b.ySize + b.zSize) / 6;
this._radius = avgRadius;
this.collider = new SphereCollisionEntity(cast this);
this.addChild(marbleDts);
// var geom = Sphere.defaultUnitSphere();
// geom.addUVs();
// var marbleTexture = ResourceLoader.getFileEntry("data/shapes/balls/base.marble.png").toTexture();
// var marbleMaterial = Material.create(marbleTexture);
// marbleMaterial.shadows = false;
// marbleMaterial.castShadows = true;
// marbleMaterial.mainPass.removeShader(marbleMaterial.textureShader);
// var dtsShader = new DtsTexture();
// dtsShader.texture = marbleTexture;
// dtsShader.currentOpacity = 1;
// marbleMaterial.mainPass.addShader(dtsShader);
var obj = new Mesh(geom, marbleMaterial, this);
obj.scale(_radius);
if (Settings.optionsSettings.reflectiveMarble) {
this.cubemapRenderer = new CubemapRenderer(level.scene);
marbleMaterial.mainPass.addShader(new MarbleReflection(this.cubemapRenderer.cubemap));
}
// var obj = new Mesh(geom, marbleMaterial, this);
// obj.scale(_radius * 0.1);
// if (Settings.optionsSettings.reflectiveMarble) {
// this.cubemapRenderer = new CubemapRenderer(level.scene);
// marbleMaterial.mainPass.addShader(new MarbleReflection(this.cubemapRenderer.cubemap));
// }
this.forcefield = new DtsObject();
this.forcefield.dtsPath = "data/shapes/images/glow_bounce.dts";
@ -1486,20 +1512,13 @@ class Marble extends GameObject {
teleportFadeCompletion = Util.clamp(1 - (time.currentAttemptTime - this.teleportDisableTime) / 0.5, 0, 1);
if (teleportFadeCompletion > 0) {
var mesh:Mesh = cast this.children[0];
var shad:AlphaMult = mesh.material.mainPass.getShader(AlphaMult);
if (shad == null) {
shad = new AlphaMult();
mesh.material.mainPass.addShader(shad);
mesh.material.blendMode = Alpha;
this.teleporting = true;
}
shad.alpha = Util.lerp(1, 0.25, teleportFadeCompletion);
var ourDts:DtsObject = cast this.children[0];
ourDts.setOpacity(Util.lerp(1, 0.25, teleportFadeCompletion));
this.teleporting = true;
} else {
if (this.teleporting) {
var mesh:Mesh = cast this.children[0];
mesh.material.mainPass.removeShader(mesh.material.mainPass.getShader(AlphaMult));
mesh.material.blendMode = None;
var ourDts:DtsObject = cast this.children[0];
ourDts.setOpacity(1);
this.teleporting = false;
}
}

View file

@ -34,6 +34,9 @@ typedef OptionsSettings = {
var frameRateVis:Bool;
var oobInsults:Bool;
var reflectiveMarble:Bool;
var marbleIndex:Int;
var marbleSkin:String;
var marbleModel:String;
}
typedef ControlsSettings = {
@ -88,6 +91,9 @@ class Settings {
frameRateVis: true,
oobInsults: true,
reflectiveMarble: true,
marbleIndex: 0,
marbleSkin: "base",
marbleModel: "data/shapes/balls/ball-superball.dts",
vsync: #if js true #end
#if hl
false
@ -175,7 +181,10 @@ class Settings {
controls: controlsSettings,
touch: touchSettings,
stats: playStatistics,
highscoreName: highscoreName
highscoreName: highscoreName,
marbleIndex: optionsSettings.marbleIndex,
marbleSkin: optionsSettings.marbleSkin,
marbleModel: optionsSettings.marbleModel,
};
var scoreCount = 0;
var eggCount = 0;

View file

@ -14,7 +14,7 @@ class Primitive {
var p = new Primitive();
p.firstElement = reader.readU16();
p.numElements = reader.readU16();
p.matIndex = (reader.readU32() & 0x00ffffff);
p.matIndex = reader.readU32();
return p;
}
}

View file

@ -0,0 +1,12 @@
package dts;
@:publicFields
class TSDrawPrimitive {
static var Triangles = 0 << 30;
static var Strip = 1 << 30;
static var Fan = 2 << 30;
static var Indexed = 1 << 29;
static var NoMaterial = 1 << 28;
static var MaterialMask = ~(1 << 30 | 2 << 30 | 0 << 30 | 1 << 29 | 1 << 28);
static var TypeMask = (1 << 30 | 2 << 30 | 0 << 30);
}

View file

@ -71,6 +71,19 @@ class GuiObjectShow extends GuiControl {
}
}
public function changeObject(dts:DtsObject) {
if (_initialized) {
sceneObject.remove();
sceneObject.dispose();
sceneObject = dts;
scene.addChild(sceneObject);
var objCenter = sceneObject.getBounds().getCenter();
scene.camera.pos = new Vector(0, renderDistance * Math.cos(renderPitch), objCenter.z + renderDistance * Math.sin(renderPitch));
scene.camera.target = new Vector(objCenter.x, objCenter.y, objCenter.z);
}
}
public override function renderEngine(engine:h3d.Engine) {
if (_initialized) {
engine.pushTarget(this.sceneTarget);

202
src/gui/MarbleSelectGui.hx Normal file
View file

@ -0,0 +1,202 @@
package gui;
import h2d.filter.DropShadow;
import hxd.res.BitmapFont;
import h3d.prim.Polygon;
import h3d.scene.Mesh;
import h3d.shader.AlphaChannel;
import src.MarbleGame;
import h3d.Vector;
import src.ResourceLoader;
import src.DtsObject;
import src.Settings;
class MarbleSelectGui extends GuiImage {
public function new() {
var img = ResourceLoader.getImage("data/ui/marbleSelect/marbleSelect.png");
super(img.resource.toTile());
this.horizSizing = Center;
this.vertSizing = Center;
this.position = new Vector(73, -59);
this.extent = new Vector(493, 361);
var marbleData = [
{name: "Staff's Original", dts: "data/shapes/balls/ball-superball.dts", skin: "base"},
{name: "3D Marble", dts: "data/shapes/balls/3dMarble.dts", skin: "base"},
{name: "Mid P", dts: "data/shapes/balls/midp.dts", skin: "base"},
{name: "Spade", dts: "data/shapes/balls/ball-superball.dts", skin: "skin4"},
{name: "GMD Logo", dts: "data/shapes/balls/ball-superball.dts", skin: "skin5"},
{name: "Textured Marble", dts: "data/shapes/balls/ball-superball.dts", skin: "skin6"},
{name: "Golden Marble", dts: "data/shapes/balls/ball-superball.dts", skin: "skin7"},
{name: "Rainbow Marble", dts: "data/shapes/balls/ball-superball.dts", skin: "skin8"},
{name: "Brown Swirls", dts: "data/shapes/balls/ball-superball.dts", skin: "skin9"},
{name: "Caution Stripes", dts: "data/shapes/balls/ball-superball.dts", skin: "skin10"},
{name: "Earth", dts: "data/shapes/balls/ball-superball.dts", skin: "skin11"},
{name: "Golf Ball", dts: "data/shapes/balls/ball-superball.dts", skin: "skin12"},
{name: "Jupiter", dts: "data/shapes/balls/ball-superball.dts", skin: "skin13"},
{name: "MB Gold Marble", dts: "data/shapes/balls/ball-superball.dts", skin: "skin14"},
{name: "MBP on the Marble!", dts: "data/shapes/balls/ball-superball.dts", skin: "skin15"},
{name: "Moshe", dts: "data/shapes/balls/ball-superball.dts", skin: "skin16"},
{name: "Strong Bad", dts: "data/shapes/balls/ball-superball.dts", skin: "skin17"},
{name: "Venus", dts: "data/shapes/balls/ball-superball.dts", skin: "skin18"},
{name: "Water", dts: "data/shapes/balls/ball-superball.dts", skin: "skin19"},
{name: "Evil Eye", dts: "data/shapes/balls/ball-superball.dts", skin: "skin20"},
{name: "Desert and Sky", dts: "data/shapes/balls/ball-superball.dts", skin: "skin21"},
{name: "Dirt Marble", dts: "data/shapes/balls/ball-superball.dts", skin: "skin22"},
{name: "Friction Textured Marble", dts: "data/shapes/balls/ball-superball.dts", skin: "skin23"},
{name: "Grass", dts: "data/shapes/balls/ball-superball.dts", skin: "skin24"},
{name: "Mars", dts: "data/shapes/balls/ball-superball.dts", skin: "skin25"},
{name: "Phil's Golf Ball", dts: "data/shapes/balls/ball-superball.dts", skin: "skin26"},
{name: "Molten", dts: "data/shapes/balls/ball-superball.dts", skin: "skin27"},
{name: "Lightning", dts: "data/shapes/balls/ball-superball.dts", skin: "skin28"},
{name: "Phil'sEmpire", dts: "data/shapes/balls/ball-superball.dts", skin: "skin29"},
{name: "Matan's Red Dragon", dts: "data/shapes/balls/ball-superball.dts", skin: "skin30"},
{name: "Metallic Marble", dts: "data/shapes/balls/ball-superball.dts", skin: "skin31"},
{name: "Sun", dts: "data/shapes/balls/ball-superball.dts", skin: "skin32"},
{name: "Underwater", dts: "data/shapes/balls/ball-superball.dts", skin: "skin33"},
{name: "GarageGames logo", dts: "data/shapes/balls/garageGames.dts", skin: "base"},
{name: "Big Marble 1", dts: "data/shapes/balls/bm1.dts", skin: "base"},
{name: "Big Marble 2", dts: "data/shapes/balls/bm2.dts", skin: "base"},
{name: "Big Marble 3", dts: "data/shapes/balls/bm3.dts", skin: "base"},
{name: "Small Marble 1", dts: "data/shapes/balls/sm1.dts", skin: "base"},
{name: "Small Marble 2", dts: "data/shapes/balls/sm2.dts", skin: "base"},
{name: "Small Marble 3", dts: "data/shapes/balls/sm3.dts", skin: "base"},
];
var curSelection:Int = Settings.optionsSettings.marbleIndex;
function loadButtonImages(path:String) {
var normal = ResourceLoader.getResource('${path}_n.png', ResourceLoader.getImage, this.imageResources).toTile();
var hover = ResourceLoader.getResource('${path}_h.png', ResourceLoader.getImage, this.imageResources).toTile();
var pressed = ResourceLoader.getResource('${path}_d.png', ResourceLoader.getImage, this.imageResources).toTile();
var disabled = ResourceLoader.getResource('${path}_i.png', ResourceLoader.getImage, this.imageResources).toTile();
return [normal, hover, pressed, disabled];
}
var markerFelt32fontdata = ResourceLoader.getFileEntry("data/font/MarkerFelt.fnt");
var markerFelt32b = new BitmapFont(markerFelt32fontdata.entry);
@:privateAccess markerFelt32b.loader = ResourceLoader.loader;
var markerFelt32 = markerFelt32b.toSdfFont(cast 26 * Settings.uiScale, MultiChannel);
var markerFelt24 = markerFelt32b.toSdfFont(cast 18 * Settings.uiScale, MultiChannel);
var markerFelt28 = markerFelt32b.toSdfFont(cast 26 * Settings.uiScale, MultiChannel);
var selectBtn = new GuiButton(loadButtonImages("data/ui/marbleSelect/select"));
selectBtn.horizSizing = Center;
selectBtn.vertSizing = Top;
selectBtn.position = new Vector(199, 270);
selectBtn.extent = new Vector(95, 45);
selectBtn.pressedAction = (e) -> {
Settings.optionsSettings.marbleIndex = curSelection;
Settings.optionsSettings.marbleSkin = marbleData[curSelection].skin;
Settings.optionsSettings.marbleModel = marbleData[curSelection].dts;
Settings.save();
MarbleGame.canvas.popDialog(this);
}
this.addChild(selectBtn);
var marbleShow = buildObjectShow(marbleData[curSelection].dts, new Vector(171, 97), new Vector(150, 150), 2.6, 0);
marbleShow.horizSizing = Center;
marbleShow.vertSizing = Bottom;
marbleShow.visible = true;
this.addChild(marbleShow);
var titleText = new GuiMLText(markerFelt28, null);
titleText.text.textColor = 0xFFFFFF;
titleText.text.filter = new DropShadow(1.414, 0.785, 0, 1, 0x0000007F, 0.4, 1, true);
titleText.horizSizing = Center;
titleText.vertSizing = Bottom;
titleText.position = new Vector(140, 67);
titleText.extent = new Vector(213, 27);
titleText.text.text = '<p align="center">Official Marbles</p>';
this.addChild(titleText);
var marbleText = new GuiMLText(markerFelt24, null);
marbleText.text.textColor = 0xFFFFFF;
marbleText.text.filter = new DropShadow(1.414, 0.785, 0, 1, 0x0000007F, 0.4, 1, true);
marbleText.horizSizing = Center;
marbleText.vertSizing = Bottom;
marbleText.position = new Vector(86, 243);
marbleText.extent = new Vector(320, 22);
marbleText.text.text = '<p align="center">${marbleData[curSelection].name}</p>';
this.addChild(marbleText);
var changeMarbleText = new GuiImage(ResourceLoader.getResource("data/ui/play/change_marble_text.png", ResourceLoader.getImage, this.imageResources)
.toTile());
changeMarbleText.horizSizing = Center;
changeMarbleText.position = new Vector(96, 26);
changeMarbleText.extent = new Vector(300, 39);
this.addChild(changeMarbleText);
function setMarbleSelection(idx:Int) {
if (idx < 0)
idx = marbleData.length + idx;
if (idx >= marbleData.length)
idx -= marbleData.length;
curSelection = idx;
var marble = marbleData[idx];
marbleText.text.text = '<p align="center">${marble.name}</p>';
var dtsObj = new DtsObject();
dtsObj.dtsPath = marble.dts;
dtsObj.ambientRotate = true;
dtsObj.ambientSpinFactor /= -2;
dtsObj.showSequences = false;
dtsObj.useInstancing = false;
dtsObj.matNameOverride.set("base.marble", marble.skin + ".marble");
dtsObj.init(null, () -> {}); // The lambda is not gonna run async anyway
for (mat in dtsObj.materials) {
mat.mainPass.enableLights = false;
mat.mainPass.culling = None;
if (mat.blendMode != Alpha && mat.blendMode != Add)
mat.mainPass.addShader(new AlphaChannel());
}
marbleShow.changeObject(dtsObj);
}
var nextBtn = new GuiButton(loadButtonImages("data/ui/marbleSelect/next"));
nextBtn.position = new Vector(296, 270);
nextBtn.extent = new Vector(75, 45);
nextBtn.pressedAction = (e) -> {
setMarbleSelection(curSelection + 1);
}
this.addChild(nextBtn);
var prevBtn = new GuiButton(loadButtonImages("data/ui/marbleSelect/prev"));
prevBtn.position = new Vector(123, 270);
prevBtn.extent = new Vector(75, 45);
prevBtn.pressedAction = (e) -> {
setMarbleSelection(curSelection - 1);
}
setMarbleSelection(curSelection);
this.addChild(prevBtn);
}
function buildObjectShow(dtsPath:String, position:Vector, extent:Vector, dist:Float = 5, pitch:Float = 0, matnameOverride:Map<String, String> = null) {
var oShow = new GuiObjectShow();
var dtsObj = new DtsObject();
dtsObj.dtsPath = dtsPath;
dtsObj.ambientRotate = true;
dtsObj.ambientSpinFactor /= -2;
dtsObj.showSequences = false;
dtsObj.useInstancing = false;
if (matnameOverride != null) {
for (key => value in matnameOverride) {
dtsObj.matNameOverride.set(key, value);
}
}
dtsObj.init(null, () -> {}); // The lambda is not gonna run async anyway
for (mat in dtsObj.materials) {
mat.mainPass.enableLights = false;
mat.mainPass.culling = None;
if (mat.blendMode != Alpha && mat.blendMode != Add)
mat.mainPass.addShader(new AlphaChannel());
}
oShow.sceneObject = dtsObj;
oShow.position = position;
oShow.extent = extent;
oShow.renderDistance = dist;
oShow.renderPitch = pitch;
return oShow;
}
}

View file

@ -613,6 +613,9 @@ class PlayMissionGui extends GuiImage {
var pmMarbleSelect = new GuiButton(loadButtonImages("data/ui/play/marble"));
pmMarbleSelect.position = new Vector(50, 46);
pmMarbleSelect.extent = new Vector(43, 43);
pmMarbleSelect.pressedAction = (e) -> {
MarbleGame.canvas.pushDialog(new MarbleSelectGui());
}
pmMorePopDlg.addChild(pmMarbleSelect);
var pmStats = new GuiButton(loadButtonImages("data/ui/play/statistics"));