diff --git a/commandline/commands/Update.hx b/commandline/commands/Update.hx index c354aca8..d43c3620 100644 --- a/commandline/commands/Update.hx +++ b/commandline/commands/Update.hx @@ -64,8 +64,7 @@ class Update { break; } else if (curHaxeVer[i] > requiredHaxeVer[i]) { prettyPrint("!! WARNING !!" - + "\nHaxeFlixel has incompability issues with the latest version of Haxe, 4.3.0 and above, due to macros." - + "\nProceeding will cause compilation issues related to macros (ex: cannot access flash package in macro)"); + + "\nUsing Haxe 4.3.0 and above is currently not recommended due to lack of testing."); Sys.println(''); Sys.println('We recommend downgrading back to 4.2.5.'); break; @@ -75,14 +74,36 @@ class Update { } public static function prettyPrint(text:String) { + var lines = text.split("\n"); + var length = -1; + for(line in lines) + if(line.length > length) + length = line.length; var header = "══════"; - for(i in 0...(text.length-(text.lastIndexOf("\n")+1))) + for(i in 0...length) header += "═"; Sys.println(""); Sys.println('╔$header╗'); - Sys.println('║ $text ║'); + for(line in lines) { + Sys.println('║ ${centerText(line, length)} ║'); + } Sys.println('╚$header╝'); } + + + public static function centerText(text:String, width:Int):String { + var centerOffset = (width - text.length) / 2; + var left = repeat(' ', Math.floor(centerOffset)); + var right = repeat(' ', Math.ceil(centerOffset)); + return left + text + right; + } + + public static inline function repeat(ch:String, amt:Int) { + var str = ""; + for(i in 0...amt) + str += ch; + return str; + } } typedef Library = { diff --git a/project.xml b/project.xml index 42c962e6..5d17fa17 100644 --- a/project.xml +++ b/project.xml @@ -96,17 +96,9 @@ - - - - - - - -
@@ -144,9 +136,6 @@ - - - @@ -190,10 +179,10 @@
- +
- + diff --git a/source/away3d/extrusions/PathExtrude.hx b/source/away3d/extrusions/PathExtrude.hx new file mode 100644 index 00000000..2666c1ba --- /dev/null +++ b/source/away3d/extrusions/PathExtrude.hx @@ -0,0 +1,1372 @@ +package away3d.extrusions; + +import away3d.bounds.BoundingVolumeBase; +import away3d.core.base.Geometry; +import away3d.core.base.SubGeometry; +import away3d.core.base.SubMesh; +import away3d.core.base.data.UV; +import away3d.core.base.data.Vertex; +import away3d.core.math.Vector3DUtils; +import away3d.entities.Mesh; +import away3d.extrusions.data.SubGeometryList; +import away3d.materials.MaterialBase; +import away3d.paths.IPath; +import away3d.paths.IPathSegment; +import away3d.tools.helpers.MeshHelper; + +import openfl.errors.Error; +import openfl.geom.Matrix3D; +import openfl.geom.Vector3D; +import openfl.Vector; + +class PathExtrude extends Mesh +{ + public var upAxis(get, set):Vector3D; + public var centerMesh(get, set):Bool; + public var distributeU(get, set):Bool; + public var path(get, set):IPath; + public var profile(get, set):Vector; + public var scales(get, set):Vector; + public var rotations(get, set):Vector; + public var materials(get, set):Vector; + public var subdivision(get, set):Int; + public var coverAll(get, set):Bool; + public var distribute(get, set):Bool; + public var smoothSurface(get, set):Bool; + public var coverSegment(get, set):Bool; + public var mapFit(get, set):Bool; + public var flip(get, set):Bool; + public var closePath(get, set):Bool; + public var aligntoPath(get, never):Bool; + public var alignToPath(never, set):Bool; + public var smoothScale(get, set):Bool; + public var keepExtremes(get, set):Bool; + public var startProfile(get, never):Vector; + public var endProfile(get, never):Vector; + + private var _varr:Vector; + private var _doubles:Vector = new Vector(); + private var _upAxis:Vector3D = new Vector3D(0, 1, 0); + private var _trans:Matrix3D = new Matrix3D(); + + private static inline var LIMIT:Int = 196605; + private static inline var MAXRAD:Float = 1.2; + private var _path:IPath; + private var _profile:Vector; + private var _centerMesh:Bool; + private var _scales:Vector; + private var _rotations:Vector; + private var _materials:Vector; + private var _activeMaterial:MaterialBase; + private var _subdivision:Int; + private var _coverAll:Bool; + private var _coverSegment:Bool; + private var _flip:Bool; + private var _mapFit:Bool; + private var _closePath:Bool; + private var _alignToPath:Bool; + private var _smoothScale:Bool; + private var _smoothSurface:Bool; + private var _isClosedProfile:Bool; + private var _maxIndProfile:Int; + private var _matIndex:Int = 0; + private var _segv:Float; + private var _geomDirty:Bool = true; + private var _subGeometry:SubGeometry; + private var _MaterialsSubGeometries:Vector = new Vector(); + private var _uva:UV; + private var _uvb:UV; + private var _uvc:UV; + private var _uvd:UV; + private var _uvs:Vector; + private var _vertices:Vector; + private var _indices:Vector; + private var _normals:Vector; + private var _normalTmp:Vector3D; + private var _normal0:Vector3D; + private var _normal1:Vector3D; + private var _normal2:Vector3D; + private var _keepExtremes:Bool; + private var _distribute:Bool; + private var _distributeU:Bool; + private var _distributedU:Vector; + private var _startPoints:Vector; + private var _endPoints:Vector; + + /** + * Creates a new PathExtrude + * + * @param material [optional] MaterialBase. The PathExtrude (Mesh) material. Optional in constructor, material must be set before PathExtrude object is rendered. Required for the class to work. + * @param path [optional] Path. Defines the Path object representing path to extrude along. Required for the class to work. + * @param profile [optional] Vector.<Vector3D>. Defines an Vector.<Vector3D> of Vector3D objects representing the profile information to be projected along the Path object. Required for the class to work. + * @param subdivision [optional] uint. Howmany steps between each PathSegment. If the path holds curves, the higher this value, the higher the curve fidelity. Default and minimum is 2; + * @param coverall [optional] Boolean. Defines the uv mapping, when true a unique material is stretched along the entire path/shape. Default is true. + * @param coverSegment [optional] Boolean. Defines the uv mapping, when true and coverall is false a unique material is stretched along one PathSegment. Default is false. + * @param alignToPath [optional] Boolean. If the profile must follow the path or keep its original orientation. + * @param centerMesh [optional] Boolean. If the geometry needs to be recentered in its own object space. If the position after generation is set to 0,0,0, the object would be centered in worldspace. Default is false. + * @param mapFit [optional] Boolean. The UV mapping is percentually spreaded over the width of the path, making texture looking nicer and edits for applications such as a race track, road, more easy. Affects the uv's u values and set distributeU to false. Default is false. + * @param flip [optional] Boolean. If the faces must be reversed depending on Vector3D's orientation. Default is false. + * @param closePath [optional] Boolean. If the last PathSegment entered must be welded back to first one. Executed in a straight manner, its recommanded to pass the first entry to the Path again, as last entry if curves are involved. + * @param materials [optional] Vector.<MaterialBase>. An optional Vector.<MaterialBase> of different materials that can be alternated along the path if coverAll is false. + * @param scales [optional] An optional Vector.<Vector3D> of Vector3D objects that defines a series of scales to be set on each PathSegment. + * @param smoothScale [optional] Boolean. Defines if the scale must be interpolated between values or keep their full aspect on each PathSegment. + * @param rotations [optional] An optional Vector.<Vector3D> of Vector3D objects that defines a series of rotations to be set on each PathSegment. + * @param smoothSurface [optional] An optional Boolean. Defines if the surface of the mesh must be smoothed or not. Default is true. + * @param distribute [optional] Boolean. If the mesh subdivision is evenly spreaded over the entire mesh. Depending on path definition, segments are possibly not having the same amount of subdivision. + * @param distributeU [optional] Boolean. If the mesh uv' u value is procentually spreaded over the entire mesh surface. Prevents the source map to be stretched. Default is true. + * @param keepExtremes [optional] Boolean. If the the first and last profile coordinates must be kept accessible, in order to feed classes such as DelaunayMesh. Default is false; + */ + public function new(material:MaterialBase = null, path:IPath = null, profile:Vector = null, subdivision:Int = 2, coverAll:Bool = true, coverSegment:Bool = false, alignToPath:Bool = true, centerMesh:Bool = false, mapFit:Bool = false, flip:Bool = false, closePath:Bool = false, materials:Vector = null, scales:Vector = null, smoothScale:Bool = true, rotations:Vector = null, smoothSurface:Bool = true, distribute:Bool = false, distributeU:Bool = true, keepExtremes:Bool = false) + { + var geom:Geometry = new Geometry(); + _subGeometry = new SubGeometry(); + super(geom, material); + + _activeMaterial = this.material; + _path = path; + this.profile = profile; + this.subdivision = subdivision; + _coverSegment = coverSegment; + _coverAll = (_coverSegment)? false : coverAll; + _alignToPath = alignToPath; + _centerMesh = centerMesh; + _mapFit = mapFit; + _flip = flip; + _closePath = closePath; + _materials = (materials != null)? materials : new Vector(); + _scales = scales; + _smoothScale = smoothScale; + _rotations = rotations; + _smoothSurface = smoothSurface; + _distributeU = distributeU; + _keepExtremes = keepExtremes; + } + + private function get_upAxis():Vector3D + { + return _upAxis; + } + + private function set_upAxis(value:Vector3D):Vector3D + { + _upAxis = value; + return value; + } + + /** + * @inheritDoc + */ + override private function get_bounds():BoundingVolumeBase + { + if (_geomDirty) + buildExtrude(); + + return super.bounds; + } + + /** + * @inheritDoc + */ + override private function get_geometry():Geometry + { + if (_geomDirty) + buildExtrude(); + + return super.geometry; + } + + /** + * @inheritDoc + */ + override private function get_subMeshes():Vector + { + if (_geomDirty) + buildExtrude(); + + return super.subMeshes; + } + + /** + * Defines whether the mesh is recentered of not after generation + */ + private function get_centerMesh():Bool + { + return _centerMesh; + } + + private function set_centerMesh(val:Bool):Bool + { + if (_centerMesh == val) + return val; + + _centerMesh = val; + + if (_centerMesh && this.geometry.subGeometries.length > 0) + MeshHelper.recenter(this); + else + invalidateGeometry(); + return val; + } + + /** + * Defines the uv's u values are spreaded procentually over the entire surface to prevent the maps to be stretched. + */ + private function get_distributeU():Bool + { + return _distributeU; + } + + private function set_distributeU(val:Bool):Bool + { + if (_distributeU == val) + return val; + + _distributeU = val; + + if (val && _mapFit) + _mapFit = false; + if (!val && _distributedU != null) + _distributedU = null; + + invalidateGeometry(); + return val; + } + + /** + * Invalidates the geometry, causing it to be rebuillded when requested. + */ + private function invalidateGeometry():Void + { + _geomDirty = true; + invalidateBounds(); + } + + /** + * Defines the Path object representing path to extrude along. Required. + */ + private function get_path():IPath + { + return _path; + } + + private function set_path(val:IPath):IPath + { + _path = val; + _geomDirty = true; + return val; + } + + /** + * Defines a Vector.<Vector3D> of Vector3D objects representing the profile information to be projected along the Path object. Required. + */ + private function get_profile():Vector + { + return _profile; + } + + private function set_profile(val:Vector):Vector + { + _profile = val; + + if (_profile != null) + _isClosedProfile = (_profile[0].x == _profile[_profile.length - 1].x && _profile[0].y == _profile[_profile.length - 1].y && _profile[0].z == _profile[_profile.length - 1].z); + + _geomDirty = true; + return val; + } + + /** + * An optional Vector.<Vector3D> of Vector3D objects that defines a series of scales to be set on each PathSegment. + */ + private function get_scales():Vector + { + return _scales; + } + + private function set_scales(val:Vector):Vector + { + _scales = val; + _geomDirty = true; + return val; + } + + /** + * An optional Vector.<Vector3D> of Vector3D objects that defines a series of rotations to be set on each PathSegment. + */ + private function get_rotations():Vector + { + return _rotations; + } + + private function set_rotations(val:Vector):Vector + { + _rotations = val; + _geomDirty = true; + return val; + } + + /** + * An optional Vector.<MaterialBase>. It defines a series of materials to be set on each PathSegment if coverAll is set to false. + */ + private function get_materials():Vector + { + return _materials; + } + + private function set_materials(val:Vector):Vector + { + if (val == null) + return val; + _materials = val; + _geomDirty = true; + return val; + } + + /** + * Defines the subdivisions created in the mesh for each PathSegment. Defaults to 2, minimum 2. + */ + private function get_subdivision():Int + { + return _subdivision; + } + + private function set_subdivision(val:Int):Int + { + val = (val < 2)? 2 : val; + + if (_subdivision == val) + return val; + + _subdivision = val; + _geomDirty = true; + return val; + } + + /** + * Defines if the texture(s) should be stretched to cover the entire mesh or per step between segments. Defaults to true. + */ + private function get_coverAll():Bool + { + return _coverAll; + } + + private function set_coverAll(val:Bool):Bool + { + if (_coverAll == val) + return val; + + _coverAll = val; + _geomDirty = true; + return val; + } + + /** + * Defines if the mesh subdivision is spread evenly over the entire geometry. Possibly resulting in uneven subdivision per segments. + * Uv mapping is less distorted on complex shapes once applied. Depending on Path length, extra construct time might be significant. + * Defaults to false. + */ + private function get_distribute():Bool + { + return _distribute; + } + + private function set_distribute(val:Bool):Bool + { + if (_distribute == val) + return val; + + _distribute = val; + _geomDirty = true; + return val; + } + + /** + * Defines if the surface of the mesh must be smoothed or not. + */ + private function get_smoothSurface():Bool + { + return _smoothSurface; + } + + private function set_smoothSurface(val:Bool):Bool + { + if (_smoothSurface == val) + return val; + + _smoothSurface = val; + _geomDirty = true; + return val; + } + + /** + * Defines if the texture(s) should applied per segment. Default false. + */ + private function set_coverSegment(b:Bool):Bool + { + _coverSegment = b; + return b; + } + + private function get_coverSegment():Bool + { + return _coverSegment; + } + + /** + * Defines if the texture(s) should be projected on the geometry evenly spreaded over the source bitmapdata or using distance/percent. Default is false. + * The mapping considers first and last profile points are the most distant from each other. Most left and most right on the map. + * Note that it is NOT suitable for most cases. It is helpfull for roads definition, usually seen from above with simple profile. It prevents then distorts and eases map designs. + */ + private function get_mapFit():Bool + { + return _mapFit; + } + + private function set_mapFit(val:Bool):Bool + { + if (_mapFit == val) + return val; + + if (val && _distributeU) + _distributeU = false; + + _mapFit = val; + _geomDirty = true; + return val; + } + + /** + * Defines if the generated faces should be inversed. Default false. + */ + private function get_flip():Bool + { + return _flip; + } + + private function set_flip(val:Bool):Bool + { + if (_flip == val) + return val; + + _flip = val; + _geomDirty = true; + return val; + } + + /** + * Defines if the last PathSegment should join the first one and close the loop. Defaults to false. + */ + private function get_closePath():Bool + { + return _closePath; + } + + private function set_closePath(val:Bool):Bool + { + if (_closePath == val) + return val; + + _closePath = val; + _geomDirty = true; + return val; + } + + /** + * Defines if the array of profile points should be orientated on path or not. Default true. Note that Path object's worldaxis property might need to be changed. default = 0,1,0. + * + * @see #profile + */ + private function get_aligntoPath():Bool + { + return _alignToPath; + } + + private function set_alignToPath(val:Bool):Bool + { + if (_alignToPath == val) + return val; + + _alignToPath = val; + _geomDirty = true; + return val; + } + + /** + * Defines if a scaling of a PathSegment defined from the scales array of Vector3D objects should affect the whole PathSegment evenly or be smoothly interpolated from previous PathSegment scale. Defaults to true. + */ + private function get_smoothScale():Bool + { + return _smoothScale; + } + + private function set_smoothScale(val:Bool):Bool + { + if (_smoothScale == val) + return val; + + _smoothScale = val; + _geomDirty = true; + return val; + } + + /** + * Defines if the first and last transformed vector3d's of the profile are kept. + * For instance to be able to pass these coordinates to DelaunayMesh class, to close the extrude, if it was a tube. + * @see getStartProfile + * @see getEndProfile + */ + private function get_keepExtremes():Bool + { + return _keepExtremes; + } + + private function set_keepExtremes(b:Bool):Bool + { + _keepExtremes = b; + return b; + } + + /** + * returns a vector of vector3d's representing the transformed profile coordinates at the start of the extrude shape + * null if "keepExtremes" is false or if the extrusion has not been builded yet. + */ + private function get_startProfile():Vector + { + if (_path == null || _startPoints == null) + return null; + + return _startPoints; + } + + /** + * returns a vector of vector3d's representing the transformed profile coordinates at the end of the extrude shape + * null if "keepExtremes" is false or if the extrusion has not been builded yet. + */ + private function get_endProfile():Vector + { + if (_path == null || _endPoints == null) + return null; + + return _endPoints; + } + + private function orientateAt(target:Vector3D, position:Vector3D):Void + { + var xAxis:Vector3D; + var yAxis:Vector3D; + var zAxis:Vector3D = target.subtract(position); + + zAxis.normalize(); + + if (zAxis.length > 0.1) { + xAxis = _upAxis.crossProduct(zAxis); + xAxis.normalize(); + + yAxis = xAxis.crossProduct(zAxis); + yAxis.normalize(); + + var rawData:Vector = _trans.rawData; + + rawData[0] = xAxis.x; + rawData[1] = xAxis.y; + rawData[2] = xAxis.z; + + rawData[4] = -yAxis.x; + rawData[5] = -yAxis.y; + rawData[6] = -yAxis.z; + + rawData[8] = zAxis.x; + rawData[9] = zAxis.y; + rawData[10] = zAxis.z; + + _trans.rawData = rawData; + } + } + + private function generate(points:Vector>, offsetV:Int = 0, closedata:Bool = false):Void + { + var uvlength:Int = (points.length - 1) + offsetV; + var offset:Int; + + for (i in 0...points.length - 1) { + _varr = new Vector(); + offset = (closedata)? i + uvlength : i; + + extrudePoints(points[i], points[i + 1], (1/uvlength)*offset, uvlength, offset/(_subdivision - 1)); + + if (i == 0 && _isClosedProfile) + _doubles = _varr.concat(); + } + _varr = _doubles = null; + } + + private function extrudePoints(points1:Vector, points2:Vector, vscale:Float, indexv:Int, indexp:Float):Void + { + var i:Int; + var j:Int; + + var stepx:Float; + var stepy:Float; + var stepz:Float; + + var va:Vertex; + var vb:Vertex; + var vc:Vertex; + var vd:Vertex; + + var u1:Float; + var u2:Float; + var index:Int = 0; + + var v1:Float = 0; + var v2:Float = 0; + + var countloop:Int = points1.length; + + var mat:MaterialBase; + + var dist:Float = 0; + var tdist:Float; + var bleft:Vector3D = null; + var bu:Float = 0; + var bincu:Float = 0; + + if (_mapFit) { + for (i in 0...countloop) { + for (j in 0...countloop) { + if (i != j) { + tdist = Vector3D.distance(points1[i], points1[j]); + if (tdist > dist) { + dist = tdist; + bleft = points1[i]; + } + } + } + } + + } else { + bincu = 1/(countloop - 1); + } + + function getDouble(x:Float, y:Float, z:Float):Vertex + { + for (i in 0..._doubles.length) { + if (_doubles[i].x == x && _doubles[i].y == y && _doubles[i].z == z) { + return _doubles[i]; + } + } + return new Vertex(x, y, z); + } + + for (i in 0...countloop) { + stepx = points2[i].x - points1[i].x; + stepy = points2[i].y - points1[i].y; + stepz = points2[i].z - points1[i].z; + + for (j in 0...2) { + if (_isClosedProfile && _doubles.length > 0) + _varr.push(getDouble(points1[i].x + (stepx*j), points1[i].y + (stepy*j), points1[i].z + (stepz*j))); + else + _varr.push(new Vertex(points1[i].x + (stepx*j), points1[i].y + (stepy*j), points1[i].z + (stepz*j))); + } + } + + var floored:Int = (_coverSegment) ? Std.int(indexp) : 0; + + if (_materials != null && _materials.length > 0) { + + if (_coverSegment && indexp - floored == 0) + _matIndex = (_matIndex + 1 > _materials.length - 1)? 0 : _matIndex + 1; + else if (!coverAll && !_coverSegment) + _matIndex = (_matIndex + 1 > _materials.length - 1)? 0 : _matIndex + 1; + } + + mat = (_coverAll || _materials == null || _materials.length == 0)? this.material : _materials[_matIndex]; + + var covSub:Bool = _coverAll && _subdivision > 1; + var cosegSub:Bool = _coverSegment && _subdivision > 1; + + for (i in 0...countloop) { + + if (_distributeU) { + u1 = _distributedU[i]; + u2 = _distributedU[i + 1]; + } else if (_mapFit) { + u1 = 1 - Vector3D.distance(points1[i], bleft)/dist; + u2 = 1 - Vector3D.distance(points1[i + 1], bleft)/dist; + } else { + u1 = 1 - bu; + bu += bincu; + u2 = 1 - bu; + } + + v1 = ((covSub)) ? vscale : (((cosegSub)) ? indexp - floored : 0); + v2 = ((covSub)) ? vscale + (1 / indexv) : (((cosegSub)) ? v1 + _segv : 1); + + _uva.u = u1; + _uva.v = v1; + _uvb.u = u1; + _uvb.v = v2; + _uvc.u = u2; + _uvc.v = v2; + _uvd.u = u2; + _uvd.v = v1; + + va = _varr[index]; + vb = _varr[index + 1]; + vc = _varr[index + 3]; + vd = _varr[index + 2]; + + if (_flip) { + addFace(vb, va, vc, _uvb, _uva, _uvc, mat); + addFace(vc, va, vd, _uvc, _uva, _uvd, mat); + + } else { + addFace(va, vb, vc, _uva, _uvb, _uvc, mat); + addFace(va, vc, vd, _uva, _uvc, _uvd, mat); + } + + if (_mapFit) + u1 = u2; + + index += 2; + } + } + + private function initHolders():Void + { + if (_uva == null) { + _uva = new UV(0, 0); + _uvb = new UV(0, 0); + _uvc = new UV(0, 0); + _uvd = new UV(0, 0); + _normal0 = new Vector3D(0.0, 0.0, 0.0); + _normal1 = new Vector3D(0.0, 0.0, 0.0); + _normal2 = new Vector3D(0.0, 0.0, 0.0); + _normalTmp = new Vector3D(0.0, 0.0, 0.0); + } + + if (_materials != null && _materials.length > 0) { + var sglist:SubGeometryList = new SubGeometryList(); + _MaterialsSubGeometries.push(sglist); + sglist.subGeometry = new SubGeometry(); + _subGeometry = sglist.subGeometry; + + sglist.uvs = _uvs = new Vector(); + sglist.vertices = _vertices = new Vector(); + if (_smoothSurface) + sglist.normals = _normals = new Vector(); + sglist.indices = _indices = new Vector(); + sglist.material = this.material; + if (sglist.material.name == null) + sglist.material.name = "baseMaterial"; + + _matIndex = _materials.length; + + } else { + _uvs = new Vector(); + _vertices = new Vector(); + _indices = new Vector(); + if (_smoothSurface) + _normals = new Vector() + else + _subGeometry.autoDeriveVertexNormals = true; + _subGeometry.autoDeriveVertexTangents = true; + } + } + + private function getSubGeometryListFromMaterial(mat:MaterialBase):SubGeometryList + { + var sglist:SubGeometryList = null; + + for (i in 0..._MaterialsSubGeometries.length) { + if (_MaterialsSubGeometries[i].material == mat) { + sglist = _MaterialsSubGeometries[i]; + break; + } + } + + if (sglist == null) { + sglist = new SubGeometryList(); + _MaterialsSubGeometries.push(sglist); + sglist.subGeometry = new SubGeometry(); + sglist.uvs = new Vector(); + sglist.vertices = new Vector(); + sglist.indices = new Vector(); + sglist.material = mat; + if (_smoothSurface) + sglist.normals = new Vector(); + } + + return sglist; + } + + private function calcNormal(v0:Vertex, v1:Vertex, v2:Vertex):Void + { + var dx1:Float = v2.x - v0.x; + var dy1:Float = v2.y - v0.y; + var dz1:Float = v2.z - v0.z; + var dx2:Float = v1.x - v0.x; + var dy2:Float = v1.y - v0.y; + var dz2:Float = v1.z - v0.z; + + var cx:Float = dz1 * dy2 - dy1 * dz2; + var cy:Float = dx1 * dz2 - dz1 * dx2; + var cz:Float = dy1 * dx2 - dx1 * dy2; + var d:Float = 1/Math.sqrt(cx * cx + cy * cy + cz * cz); + + _normal0.x = _normal1.x = _normal2.x = cx*d; + _normal0.y = _normal1.y = _normal2.y = cy*d; + _normal0.z = _normal1.z = _normal2.z = cz*d; + } + + private function addFace(v0:Vertex, v1:Vertex, v2:Vertex, uv0:UV, uv1:UV, uv2:UV, mat:MaterialBase):Void + { + var subGeom:SubGeometry; + var uvs:Vector; + var vertices:Vector; + var normals:Vector; + var indices:Vector; + var sglist:SubGeometryList; + var startMat:Bool = false; + + if (_activeMaterial != mat && _materials != null && _materials.length > 0) { + _activeMaterial = mat; + sglist = getSubGeometryListFromMaterial(mat); + _subGeometry = subGeom = sglist.subGeometry; + _uvs = uvs = sglist.uvs; + _vertices = vertices = sglist.vertices; + _indices = indices = sglist.indices; + _normals = normals = sglist.normals; + startMat = true; + + } else { + subGeom = _subGeometry; + uvs = _uvs; + vertices = _vertices; + indices = _indices; + normals = _normals; + } + + if (vertices.length + 9 > LIMIT) { + subGeom.updateVertexData(vertices); + subGeom.updateIndexData(indices); + subGeom.updateUVData(uvs); + if (_smoothSurface) + subGeom.updateVertexNormalData(normals); + + this.geometry.addSubGeometry(subGeom); + this.subMeshes[this.subMeshes.length - 1].material = mat; + + subGeom = new SubGeometry(); + subGeom.autoDeriveVertexTangents = true; + if (!_smoothSurface) + subGeom.autoDeriveVertexNormals = true; + + if (_MaterialsSubGeometries != null && _MaterialsSubGeometries.length > 1) { + + sglist = getSubGeometryListFromMaterial(mat); + sglist.subGeometry = _subGeometry = subGeom; + sglist.uvs = _uvs = uvs = new Vector(); + sglist.vertices = _vertices = vertices = new Vector(); + sglist.indices = _indices = indices = new Vector(); + if (_smoothSurface) + sglist.normals = _normals = normals = new Vector(); + + } else { + + _subGeometry = subGeom; + uvs = _uvs = new Vector(); + vertices = _vertices = new Vector(); + indices = _indices = new Vector(); + normals = _normals = new Vector(); + } + } + + var bv0:Bool = false; + var bv1:Bool = false; + var bv2:Bool = false; + + var ind0:Int = 0; + var ind1:Int = 0; + var ind2:Int = 0; + + if (_smoothSurface && !startMat) { + var uvind:Int; + var uvindV:Int; + var vind:Int; + var vindy:Int; + var vindz:Int; + var ind:Int; + var indlength:Int = indices.length; + calcNormal(v0, v1, v2); + var ab:Float; + + if (indlength > 0) { + var back:Float = indlength - _maxIndProfile; + var limitBack:Int = ((back < 0)) ? 0 : Std.int(back); + + var i:Int = indlength - 1; + while (i > limitBack) { + ind = indices[i]; + vind = ind*3; + vindy = vind + 1; + vindz = vind + 2; + uvind = ind*2; + uvindV = uvind + 1; + + if (bv0 && bv1 && bv2) + break; + + if (!bv0 && vertices[vind] == v0.x && vertices[vindy] == v0.y && vertices[vindz] == v0.z) { + + _normalTmp.x = normals[vind]; + _normalTmp.y = normals[vindy]; + _normalTmp.z = normals[vindz]; + ab = Vector3D.angleBetween(_normalTmp, _normal0); + + if (ab < MAXRAD) { + _normal0.x = (_normalTmp.x + _normal0.x)*.5; + _normal0.y = (_normalTmp.y + _normal0.y)*.5; + _normal0.z = (_normalTmp.z + _normal0.z)*.5; + + if (_coverAll || uvs[uvind] == uv0.u && uvs[uvindV] == uv0.v) { + bv0 = true; + ind0 = ind; + --i; + continue; + } + } + } + + if (!bv1 && vertices[vind] == v1.x && vertices[vindy] == v1.y && vertices[vindz] == v1.z) { + + _normalTmp.x = normals[vind]; + _normalTmp.y = normals[vindy]; + _normalTmp.z = normals[vindz]; + ab = Vector3D.angleBetween(_normalTmp, _normal1); + + if (ab < MAXRAD) { + _normal1.x = (_normalTmp.x + _normal1.x)*.5; + _normal1.y = (_normalTmp.y + _normal1.y)*.5; + _normal1.z = (_normalTmp.z + _normal1.z)*.5; + + if (_coverAll || uvs[uvind] == uv1.u && uvs[uvindV] == uv1.v) { + bv1 = true; + ind1 = ind; + --i; + continue; + } + } + } + + if (!bv2 && vertices[vind] == v2.x && vertices[vindy] == v2.y && vertices[vindz] == v2.z) { + + _normalTmp.x = normals[vind]; + _normalTmp.y = normals[vindy]; + _normalTmp.z = normals[vindz]; + ab = Vector3D.angleBetween(_normalTmp, _normal2); + + if (ab < MAXRAD) { + _normal2.x = (_normalTmp.x + _normal2.x)*.5; + _normal2.y = (_normalTmp.y + _normal2.y)*.5; + _normal2.z = (_normalTmp.z + _normal2.z)*.5; + + if (_coverAll || uvs[uvind] == uv2.u && uvs[uvindV] == uv2.v) { + bv2 = true; + ind2 = ind; + --i; + continue; + } + } + + } + --i; + } + } + } + + if (!bv0) { + ind0 = Std.int(vertices.length / 3); + vertices.push(v0.x); + vertices.push(v0.y); + vertices.push(v0.z); + uvs.push(uv0.u); + uvs.push(uv0.v); + if (_smoothSurface) { + normals.push(_normal0.x); + normals.push(_normal0.y); + normals.push(_normal0.z); + } + } + + if (!bv1) { + ind1 = Std.int(vertices.length / 3); + vertices.push(v1.x); + vertices.push(v1.y); + vertices.push(v1.z); + uvs.push(uv1.u); + uvs.push(uv1.v); + if (_smoothSurface) { + normals.push(_normal1.x); + normals.push(_normal1.y); + normals.push(_normal1.z); + } + } + + if (!bv2) { + ind2 = Std.int(vertices.length / 3); + vertices.push(v2.x); + vertices.push(v2.y); + vertices.push(v2.z); + uvs.push(uv2.u); + uvs.push(uv2.v); + if (_smoothSurface) { + normals.push(_normal2.x); + normals.push(_normal2.y); + normals.push(_normal2.z); + } + } + + indices.push(ind0); + indices.push(ind1); + indices.push(ind2); + } + + private function distributeVectors():Vector> + { + var segs:Vector> = _path.getPointsOnCurvePerSegment(_subdivision); + var nSegs:Vector> = new Vector>(); + + var seg:Vector; + var j:Int = 0; + var estLength:Float = 0; + var vCount:Int = 0; + + var v:Vector3D; + var tmpV:Vector3D = new Vector3D(); + var prevV:Vector3D = null; + + for (i in 0...segs.length) { + seg = segs[i]; + for (j in 0..._subdivision) { + if (prevV != null) + estLength += Vector3D.distance(prevV, seg[j]); + prevV = seg[j]; + vCount++; + } + } + var step:Float = estLength/vCount; + var tPrecision:Float = 0.001; + var t:Float = 0; + var ps:IPathSegment; + + var tmpVDist:Float = 0; + var diff:Float = 0; + var ignore:Bool; + + for (i in 0...segs.length) { + ps = _path.getSegmentAt(i); + ignore = false; + t = diff; + seg = new Vector(); + + while (t < 1) { + + if (segs.length == 0) { + v = segs[i][0]; + seg.push(v); + prevV = v; + continue; + } + + tmpVDist = 0; + while (tmpVDist < step) { + t += tPrecision; + if (t > 1 && i < segs.length - 1) { + ignore = true; + break; + } else { + tmpV = ps.getPointOnSegment(t, tmpV); + tmpVDist = Vector3D.distance(prevV, tmpV); + } + } + + diff = 1 - t; + if (!ignore) { + v = new Vector3D(tmpV.x, tmpV.y, tmpV.z); + prevV = v; + seg.push(v); + } + } + + nSegs.push(seg); + } + + segs = null; + + return nSegs; + } + + private function generateUlist():Void + { + _distributedU = Vector.ofArray(cast [0]); + var tdist:Float = 0; + var dist:Float = 0; + var tmpDists:Vector = new Vector(); + for (i in 0..._profile.length - 1) { + tmpDists[i] = Vector3D.distance(_profile[i], _profile[i + 1]); + tdist += tmpDists[i]; + } + for (i in 1..._profile.length) { + _distributedU[i] = (tmpDists[i - 1] + dist)/tdist; + dist += tmpDists[i - 1]; + } + + tmpDists = null; + } + + private function buildExtrude():Void + { + if (_path == null || _path.numSegments == 0 || _profile == null || _profile.length < 2) + throw new Error("PathExtrude error: invalid Path or profile with unsufficient data"); + + _geomDirty = false; + initHolders(); + + _maxIndProfile = _profile.length*9; + + var vSegPts:Vector> = null; + + if (_distribute) + vSegPts = distributeVectors(); + else + vSegPts = _path.getPointsOnCurvePerSegment(_subdivision); + + if (_distributeU) + generateUlist(); + + var vPtsList:Vector = new Vector(); + var vSegResults:Vector> = new Vector>(); + var atmp:Vector = null; + var tmppt:Vector3D = new Vector3D(0, 0, 0); + + var i:Int = 0; + var j:Int = 0; + var k:Int = 0; + + var nextpt:Vector3D = null; + if (_coverSegment) + _segv = 1 / (_subdivision - 1); + + var lastP:Vector = null; + if (_closePath) + lastP = new Vector(); + + var rescale:Bool = (_scales != null); + var lastscale:Vector3D = null; + if (rescale) + lastscale = ((_scales[0] == null)) ? new Vector3D(1, 1, 1) : _scales[0]; + + var rotate:Bool = (_rotations != null); + + var lastrotate:Vector3D = null; + var nextrotate:Vector3D = null; + var rotation:Vector = null ; + var tweenrot:Vector3D = null; + var nextscale:Vector3D = null; + var vScales:Vector = null; + + if (rotate && _rotations.length > 0) { + lastrotate = _rotations[0]; + rotation = new Vector(); + } + + if (_smoothScale && rescale) { + nextscale = new Vector3D(1, 1, 1); + vScales = Vector.ofArray(cast [lastscale]); + if (_scales.length != _path.numSegments + 2) { + var lastScl:Vector3D = _scales[_scales.length - 1]; + while (_scales.length != _path.numSegments + 2) + _scales.push(lastScl); + } + } + + var tmploop:Int = _profile.length; + for (i in 0...vSegPts.length) { + if (rotate) { + lastrotate = ((_rotations[i] == null)) ? lastrotate : _rotations[i]; + nextrotate = ((_rotations[i + 1] == null)) ? lastrotate : _rotations[i + 1]; + rotation = Vector.ofArray(cast [lastrotate]); + rotation = rotation.concat(Vector3DUtils.subdivide(lastrotate, nextrotate, _subdivision)); + } + + if (rescale) + lastscale = ((_scales[i] == null)) ? lastscale : _scales[i]; + + if (_smoothScale && rescale) { + nextscale = ((_scales[i + 1] == null)) ? ((_scales[i] == null)) ? lastscale : _scales[i] : _scales[i + 1]; + vScales = vScales.concat(Vector3DUtils.subdivide(lastscale, nextscale, _subdivision)); + } + + for (j in 0...vSegPts[i].length) { + + atmp = new Vector(); + atmp = atmp.concat(_profile); + vPtsList = new Vector(); + + if (rotate) + tweenrot = rotation[j]; + + if (_alignToPath) { + _trans = new Matrix3D(); + if (i == vSegPts.length - 1 && j == vSegPts[i].length - 1) { + + if (_closePath) { + nextpt = vSegPts[0][0]; + orientateAt(nextpt, vSegPts[i][j]); + } else { + nextpt = vSegPts[i][j - 1]; + orientateAt(vSegPts[i][j], nextpt); + } + + } else { + nextpt = ((j < vSegPts[i].length - 1)) ? vSegPts[i][j + 1] : vSegPts[i + 1][0]; + orientateAt(nextpt, vSegPts[i][j]); + } + + } + + for (k in 0...tmploop) { + + if (rescale && !_smoothScale) { + atmp[k].x *= lastscale.x; + atmp[k].y *= lastscale.y; + atmp[k].z *= lastscale.z; + } + + if (_alignToPath) { + tmppt = new Vector3D(); + + tmppt.x = atmp[k].x * _trans.rawData[0] + atmp[k].y * _trans.rawData[4] + atmp[k].z * _trans.rawData[8] + _trans.rawData[12]; + tmppt.y = atmp[k].x * _trans.rawData[1] + atmp[k].y * _trans.rawData[5] + atmp[k].z * _trans.rawData[9] + _trans.rawData[13]; + tmppt.z = atmp[k].x * _trans.rawData[2] + atmp[k].y * _trans.rawData[6] + atmp[k].z * _trans.rawData[10] + _trans.rawData[14]; + + if (rotate) + tmppt = Vector3DUtils.rotatePoint(tmppt, tweenrot); + + tmppt.x += vSegPts[i][j].x; + tmppt.y += vSegPts[i][j].y; + tmppt.z += vSegPts[i][j].z; + + } else + tmppt = new Vector3D(atmp[k].x + vSegPts[i][j].x, atmp[k].y + vSegPts[i][j].y, atmp[k].z + vSegPts[i][j].z); + + vPtsList.push(tmppt); + } + + if (_closePath && i == vSegPts.length - 1 && j == vSegPts[i].length - 1) + break; + + if (_closePath) + lastP = vPtsList; + + vSegResults.push(vPtsList); + + } + } + + if (rescale && _smoothScale) { + for (i in 0...vScales.length) { + for (j in 0...vSegResults[i].length) { + vSegResults[i][j].x *= vScales[i].x; + vSegResults[i][j].y *= vScales[i].y; + vSegResults[i][j].z *= vScales[i].z; + } + } + vScales = null; + } + + if (rotate) + rotation = null; + + if (_closePath) { + var stepx:Float; + var stepy:Float; + var stepz:Float; + var c:Vector; + var c2:Vector> = new Vector>(); + + for (i in 1..._subdivision + 1) { + c = new Vector(); + for (j in 0...lastP.length) { + stepx = (vSegResults[0][j].x - lastP[j].x) / _subdivision; + stepy = (vSegResults[0][j].y - lastP[j].y) / _subdivision; + stepz = (vSegResults[0][j].z - lastP[j].z) / _subdivision; + c.push(new Vector3D(lastP[j].x + (stepx * i), lastP[j].y + (stepy * i), lastP[j].z + (stepz * i))); + } + c2.push(c); + } + + c2[0] = lastP; + generate(c2, (_coverAll)? vSegResults.length : 0, _coverAll); + c = null; + c2 = null; + } + + if (_keepExtremes) { + _startPoints = new Vector(); + _endPoints = new Vector(); + var offsetEnd:Int = vSegResults.length - 1; + + for (i in 0...tmploop) { + _startPoints[i] = vSegResults[0][i]; + _endPoints[i] = vSegResults[offsetEnd][i]; + } + + } else if (_startPoints != null) { + + for (i in 0...tmploop) + _startPoints[i] = _endPoints[i] = null; + _startPoints = _endPoints = null; + } + + generate(vSegResults, (_closePath && _coverAll)? 1 : 0, (_closePath && !_coverAll)); + + vSegPts = null; + _varr = null; + + if (_MaterialsSubGeometries != null && _MaterialsSubGeometries.length > 0) { + var sglist:SubGeometryList; + var sg:SubGeometry; + for (i in 0..._MaterialsSubGeometries.length) { + sglist = _MaterialsSubGeometries[i]; + sg = sglist.subGeometry; + if (sg != null && sglist.vertices.length > 0) { + this.geometry.addSubGeometry(sg); + this.subMeshes[this.subMeshes.length - 1].material = sglist.material; + sg.updateVertexData(sglist.vertices); + sg.updateIndexData(sglist.indices); + sg.updateUVData(sglist.uvs); + + if (_smoothSurface) + sg.updateVertexNormalData(sglist.normals); + } + } + + } else { + + _subGeometry.updateVertexData(_vertices); + _subGeometry.updateIndexData(_indices); + _subGeometry.updateUVData(_uvs); + + if (_smoothSurface) + _subGeometry.updateVertexNormalData(_normals); + + this.geometry.addSubGeometry(_subGeometry); + } + + if (_centerMesh) + MeshHelper.recenter(this); + } +} \ No newline at end of file diff --git a/source/away3d/materials/methods/LightMapMethod.hx b/source/away3d/materials/methods/LightMapMethod.hx new file mode 100644 index 00000000..4ac81fb6 --- /dev/null +++ b/source/away3d/materials/methods/LightMapMethod.hx @@ -0,0 +1,127 @@ +package away3d.materials.methods; + +import away3d.core.managers.Stage3DProxy; +import away3d.materials.compilation.ShaderRegisterCache; +import away3d.materials.compilation.ShaderRegisterElement; +import away3d.textures.Texture2DBase; + +import openfl.display.BlendMode; +import openfl.errors.Error; + +/** + * LightMapMethod provides a method that allows applying a light map texture to the calculated pixel colour. + * It is different from LightMapDiffuseMethod in that the latter only modulates the diffuse shading value rather + * than the whole pixel colour. + */ +class LightMapMethod extends EffectMethodBase +{ + public var blendMode(get, set):BlendMode; + public var texture(get, set):Texture2DBase; + + /** + * Indicates the light map should be multiplied with the calculated shading result. + */ + public static inline var MULTIPLY:BlendMode = BlendMode.MULTIPLY; + + /** + * Indicates the light map should be added into the calculated shading result. + */ + public static var ADD:BlendMode = BlendMode.ADD; + + private var _texture:Texture2DBase; + + private var _blendMode:BlendMode; + private var _useSecondaryUV:Bool; + + /** + * Creates a new LightMapMethod object. + * @param texture The texture containing the light map. + * @param blendMode The blend mode with which the light map should be applied to the lighting result. + * @param useSecondaryUV Indicates whether the secondary UV set should be used to map the light map. + */ + public function new(texture:Texture2DBase, blendMode:BlendMode = MULTIPLY, useSecondaryUV:Bool = false) + { + super(); + _useSecondaryUV = useSecondaryUV; + _texture = texture; + this.blendMode = blendMode; + } + + /** + * @inheritDoc + */ + override private function initVO(vo:MethodVO):Void + { + vo.needsUV = !_useSecondaryUV; + vo.needsSecondaryUV = _useSecondaryUV; + } + + /** + * The blend mode with which the light map should be applied to the lighting result. + * + * @see LightMapMethod.ADD + * @see LightMapMethod.MULTIPLY + */ + private function get_blendMode():BlendMode + { + return _blendMode; + } + + private function set_blendMode(value:BlendMode):BlendMode + { + if (value != ADD && value != MULTIPLY) + throw new Error("Unknown blendmode!"); + if (_blendMode == value) + return value; + _blendMode = value; + invalidateShaderProgram(); + return value; + } + + /** + * The texture containing the light map. + */ + private function get_texture():Texture2DBase + { + return _texture; + } + + private function set_texture(value:Texture2DBase):Texture2DBase + { + if (value.hasMipMaps != _texture.hasMipMaps || value.format != _texture.format) + invalidateShaderProgram(); + _texture = value; + return value; + } + + /** + * @inheritDoc + */ + override private function activate(vo:MethodVO, stage3DProxy:Stage3DProxy):Void + { + stage3DProxy._context3D.setTextureAt(vo.texturesIndex, _texture.getTextureForStage3D(stage3DProxy)); + super.activate(vo, stage3DProxy); + } + + /** + * @inheritDoc + */ + override private function getFragmentCode(vo:MethodVO, regCache:ShaderRegisterCache, targetReg:ShaderRegisterElement):String + { + var code:String; + var lightMapReg:ShaderRegisterElement = regCache.getFreeTextureReg(); + var temp:ShaderRegisterElement = regCache.getFreeFragmentVectorTemp(); + vo.texturesIndex = lightMapReg.index; + + code = getTex2DSampleCode(vo, temp, lightMapReg, _texture, _useSecondaryUV? _sharedRegisters.secondaryUVVarying : _sharedRegisters.uvVarying); + + switch (_blendMode) { + case BlendMode.MULTIPLY: + code += "mul " + targetReg + ", " + targetReg + ", " + temp + "\n"; + case BlendMode.ADD: + code += "add " + targetReg + ", " + targetReg + ", " + temp + "\n"; + default: + } + return code; + } +} \ No newline at end of file diff --git a/source/funkin/backend/FunkinSprite.hx b/source/funkin/backend/FunkinSprite.hx index 53e87114..ec8183ce 100644 --- a/source/funkin/backend/FunkinSprite.hx +++ b/source/funkin/backend/FunkinSprite.hx @@ -13,8 +13,7 @@ import flixel.math.FlxRect; import flixel.math.FlxPoint; import funkin.backend.system.interfaces.IBeatReceiver; -@:enum -abstract XMLAnimType(Int) +enum abstract XMLAnimType(Int) { var NONE = 0; var BEAT = 1; diff --git a/source/funkin/backend/MusicBeatState.hx b/source/funkin/backend/MusicBeatState.hx index c89728a9..35b684e5 100644 --- a/source/funkin/backend/MusicBeatState.hx +++ b/source/funkin/backend/MusicBeatState.hx @@ -1,6 +1,5 @@ package funkin.backend; -import flixel.addons.transition.FlxTransitionableState; import funkin.backend.system.framerate.Framerate; import funkin.backend.system.GraphicCacheSprite; import funkin.backend.system.Controls; diff --git a/source/funkin/backend/MusicBeatSubstate.hx b/source/funkin/backend/MusicBeatSubstate.hx index d8940afc..e2bbb312 100644 --- a/source/funkin/backend/MusicBeatSubstate.hx +++ b/source/funkin/backend/MusicBeatSubstate.hx @@ -6,7 +6,6 @@ import funkin.backend.scripting.Script; import funkin.backend.scripting.ScriptPack; import funkin.backend.scripting.DummyScript; import funkin.backend.system.interfaces.IBeatReceiver; -import funkin.backend.system.Conductor.BPMChangeEvent; import funkin.backend.system.Conductor; import funkin.backend.system.Controls; import funkin.options.PlayerSettings; diff --git a/source/funkin/backend/assets/ModdableAssetsFolder.hx b/source/funkin/backend/assets/ModdableAssetsFolder.hx index 0da7ed5f..c9ca2e16 100644 --- a/source/funkin/backend/assets/ModdableAssetsFolder.hx +++ b/source/funkin/backend/assets/ModdableAssetsFolder.hx @@ -15,7 +15,7 @@ class ModdableAssetsFolder extends ModsFolderLibrary { return super.exists(id, type); } - public override function getAsset(id:String, type:String) { + public override function getAsset(id:String, type:String):Dynamic { if (!id.startsWith("assets/")) { var possibleReplacement = getAsset('assets/$id', type); if (possibleReplacement != null) diff --git a/source/funkin/backend/scripting/HScript.hx b/source/funkin/backend/scripting/HScript.hx index be108c5f..37aaaa95 100644 --- a/source/funkin/backend/scripting/HScript.hx +++ b/source/funkin/backend/scripting/HScript.hx @@ -45,7 +45,9 @@ class HScript extends Script { this.trace(v); })); + #if GLOBAL_SCRIPT funkin.backend.scripting.GlobalScript.call("onScriptCreated", [this, "hscript"]); + #end loadFromString(code); } diff --git a/source/funkin/backend/scripting/events/PlayAnimEvent.hx b/source/funkin/backend/scripting/events/PlayAnimEvent.hx index 7d5499ba..ca88c408 100644 --- a/source/funkin/backend/scripting/events/PlayAnimEvent.hx +++ b/source/funkin/backend/scripting/events/PlayAnimEvent.hx @@ -30,8 +30,7 @@ final class PlayAnimEvent extends CancellableEvent { /** Contains all contexts possible for `PlayAnimEvent`. **/ -@:enum -abstract PlayAnimContext(String) { +enum abstract PlayAnimContext(String) { /** No context was given for the animation. The character won't dance until the animation is finished diff --git a/source/funkin/backend/system/Conductor.hx b/source/funkin/backend/system/Conductor.hx index 696db005..8db60b36 100644 --- a/source/funkin/backend/system/Conductor.hx +++ b/source/funkin/backend/system/Conductor.hx @@ -1,17 +1,10 @@ package funkin.backend.system; -import funkin.backend.chart.Chart; import funkin.backend.chart.ChartData; -import openfl.Lib; import flixel.FlxState; import funkin.backend.system.interfaces.IBeatReceiver; import flixel.util.FlxSignal.FlxTypedSignal; -/** - * ... - * @author - */ - typedef BPMChangeEvent = { var stepTime:Float; diff --git a/source/funkin/backend/system/ErrorCode.hx b/source/funkin/backend/system/ErrorCode.hx index 9959df82..c1121c0e 100644 --- a/source/funkin/backend/system/ErrorCode.hx +++ b/source/funkin/backend/system/ErrorCode.hx @@ -1,7 +1,6 @@ package funkin.backend.system; -@:enum -abstract ErrorCode(Int) { +enum abstract ErrorCode(Int) { var OK = 0; var FAILED = 1; var MISSING_PROPERTY = 2; diff --git a/source/funkin/backend/system/Main.hx b/source/funkin/backend/system/Main.hx index d715103e..87bd26d8 100644 --- a/source/funkin/backend/system/Main.hx +++ b/source/funkin/backend/system/Main.hx @@ -4,26 +4,17 @@ import funkin.editors.SaveWarning; import funkin.backend.assets.AssetsLibraryList; import funkin.backend.system.framerate.SystemInfo; import openfl.utils.AssetLibrary; -import openfl.utils.AssetCache; import openfl.text.TextFormat; import flixel.system.ui.FlxSoundTray; -import funkin.backend.utils.NativeAPI; -import funkin.menus.BetaWarningState; -import funkin.menus.TitleState; -import flixel.FlxGame; -import flixel.FlxState; import openfl.Assets; import openfl.Lib; -import openfl.display.FPS; import openfl.display.Sprite; -import openfl.events.Event; import flixel.graphics.FlxGraphic; import flixel.addons.transition.FlxTransitionableState; import flixel.addons.transition.FlxTransitionSprite.GraphicTransTileDiamond; import flixel.addons.transition.TransitionData; import flixel.math.FlxPoint; import flixel.math.FlxRect; -import lime.app.Application; import funkin.backend.system.modules.*; #if ALLOW_MULTITHREADING @@ -78,7 +69,6 @@ class Main extends Sprite #if (!mobile && !web) addChild(framerateSprite = new funkin.backend.system.framerate.Framerate()); - framerateSprite.scaleX = framerateSprite.scaleY = stage.window.scale; SystemInfo.init(); #end } diff --git a/source/funkin/backend/system/github/GitHubUser.hx b/source/funkin/backend/system/github/GitHubUser.hx index 4f817891..e0dc15bc 100644 --- a/source/funkin/backend/system/github/GitHubUser.hx +++ b/source/funkin/backend/system/github/GitHubUser.hx @@ -125,8 +125,7 @@ typedef GitHubUser = { var updated_at:String; } -@:enum -abstract GitHubUserType(String) { +enum abstract GitHubUserType(String) { var USER = "User"; var ORGANIZATION = "Organization"; } \ No newline at end of file diff --git a/source/funkin/backend/system/macros/DefinesMacro.hx b/source/funkin/backend/system/macros/DefinesMacro.hx index b7a8b96e..da257223 100644 --- a/source/funkin/backend/system/macros/DefinesMacro.hx +++ b/source/funkin/backend/system/macros/DefinesMacro.hx @@ -1,9 +1,7 @@ package funkin.backend.system.macros; #if macro -import sys.io.Process; import haxe.macro.Context; -import haxe.macro.Compiler; import haxe.macro.Expr; #end diff --git a/source/funkin/backend/system/macros/EventMacro.hx b/source/funkin/backend/system/macros/EventMacro.hx index 3a0f72dc..810ff1fd 100644 --- a/source/funkin/backend/system/macros/EventMacro.hx +++ b/source/funkin/backend/system/macros/EventMacro.hx @@ -1,6 +1,9 @@ package funkin.backend.system.macros; #if macro +import haxe.macro.Context; +import haxe.macro.Expr; + /** * Macro that generates all additional fields, making events much easier to code in. * It adds the `recycle` function, which allows you to "reset" an event's values. @@ -19,7 +22,6 @@ class EventMacro { if (f.name == "recycle") return fields; - // gets all fields var values:Array = []; var hiddenValues:Array = []; @@ -48,8 +50,8 @@ class EventMacro { // add recycle option var func:Function = { args: [for(a in values) { - value: a.expr, - type: a.type, + value: a.expr, + type: a.type, opt: false, name: a.name }], @@ -87,7 +89,7 @@ class EventMacro { }) }); } - + // add a "set this" expr to reset each private/hidden variables for(v in hiddenValues) { var name = v.name; diff --git a/source/funkin/backend/system/macros/FunkinSaveMacro.hx b/source/funkin/backend/system/macros/FunkinSaveMacro.hx index f1c2207d..11632991 100644 --- a/source/funkin/backend/system/macros/FunkinSaveMacro.hx +++ b/source/funkin/backend/system/macros/FunkinSaveMacro.hx @@ -1,6 +1,9 @@ package funkin.backend.system.macros; #if macro +import haxe.macro.Context; +import haxe.macro.Expr; + /** * Macro that automatically generates flush and load functions. */ @@ -13,7 +16,6 @@ class FunkinSaveMacro { * @return Array */ public static function build(saveFieldName:String = "save", saveFuncName:String = "flush", loadFuncName:String = "load"):Array { - var fields:Array = Context.getBuildFields(); var fieldNames:Array = []; diff --git a/source/funkin/backend/system/macros/HashLinkFixer.hx b/source/funkin/backend/system/macros/HashLinkFixer.hx index 6c1b396f..046929e8 100644 --- a/source/funkin/backend/system/macros/HashLinkFixer.hx +++ b/source/funkin/backend/system/macros/HashLinkFixer.hx @@ -1,17 +1,8 @@ package funkin.backend.system.macros; #if macro -import haxe.macro.Type.ClassType; -import Type.ValueType; -import haxe.macro.Expr.Function; import haxe.macro.Expr; -import haxe.macro.Type.MetaAccess; -import haxe.macro.Type.FieldKind; -import haxe.macro.Type.ClassField; -import haxe.macro.Type.VarAccess; import haxe.macro.*; -import Sys; -import haxe.io.Path; using StringTools; using haxe.macro.PositionTools; @@ -30,12 +21,12 @@ class HashLinkFixer { public static function init() { #if !display - #if HL - for(apply in applyOn) { - compile(apply); + if(Context.defined("hl")) { + for(apply in applyOn) { + compile(apply); + } } #end - #end } public static function compile(name:String) { diff --git a/source/funkin/backend/system/macros/ScriptsMacro.hx b/source/funkin/backend/system/macros/Macros.hx similarity index 63% rename from source/funkin/backend/system/macros/ScriptsMacro.hx rename to source/funkin/backend/system/macros/Macros.hx index 0014af3d..9183e4a4 100644 --- a/source/funkin/backend/system/macros/ScriptsMacro.hx +++ b/source/funkin/backend/system/macros/Macros.hx @@ -1,14 +1,13 @@ package funkin.backend.system.macros; #if macro -import haxe.macro.Context; -import haxe.macro.Compiler; +import haxe.macro.*; import haxe.macro.Expr; /** * Macros containing additional help functions to expand HScript capabilities. */ -class ScriptsMacro { +class Macros { public static function addAdditionalClasses() { for(inc in [ // FLIXEL @@ -27,19 +26,25 @@ class ScriptsMacro { ]) Compiler.include(inc); - for(inc in [#if SYS "sys", "openfl.net", "funkin.backend.system.net" #end]) { - #if !HL - Compiler.include(inc); - #else - // TODO: Hashlink - //Compiler.include(inc, ["sys.net.UdpSocket", "openfl.net.DatagramSocket"]); // fixes FATAL ERROR : Failed to load function std@socket_set_broadcast - #end + var isHl = Context.defined("hl"); + + if(Context.defined("sys")) { + for(inc in ["sys", "openfl.net", "funkin.backend.system.net"]) { + if(!isHl) + Compiler.include(inc); + else { + // TODO: Hashlink + //Compiler.include(inc, ["sys.net.UdpSocket", "openfl.net.DatagramSocket"]); // fixes FATAL ERROR : Failed to load function std@socket_set_broadcast + } + } } - Compiler.include("funkin", #if !UPDATE_CHECKING ['funkin.backend.system.updating'] #end); + Compiler.include("funkin", [#if !UPDATE_CHECKING 'funkin.backend.system.updating' #end]); + } - #if HL HashLinkFixer.init(); #end - // Todo rewrite this to use if(Context.defined("")) + public static function initMacros() { + if(Context.defined("hl")) + HashLinkFixer.init(); } } #end \ No newline at end of file diff --git a/source/funkin/backend/system/macros/NewHaxeWarning.hx b/source/funkin/backend/system/macros/NewHaxeWarning.hx index 88a00e9a..ee467955 100644 --- a/source/funkin/backend/system/macros/NewHaxeWarning.hx +++ b/source/funkin/backend/system/macros/NewHaxeWarning.hx @@ -6,7 +6,7 @@ class NewHaxeWarning { #if (haxe >= "4.3.0") Sys.println("===================="); Sys.println("[ WARNING ]"); - Sys.println("Compiling with Haxe 4.3.0 or above CAN and WILL end up in compilation errors due to changes in macros."); + Sys.println("Compiling with Haxe 4.3.0 isnt fully recommended yet, but it does work."); Sys.println("We recommend building the project using Haxe 4.2.5."); Sys.println("You can download it here -> https://haxe.org/download/version/4.2.5/"); Sys.println("===================="); diff --git a/source/funkin/backend/system/macros/OptionsMacro.hx b/source/funkin/backend/system/macros/OptionsMacro.hx index b3503f5d..ae54eb66 100644 --- a/source/funkin/backend/system/macros/OptionsMacro.hx +++ b/source/funkin/backend/system/macros/OptionsMacro.hx @@ -1,8 +1,10 @@ package funkin.backend.system.macros; #if macro -using StringTools; +import haxe.macro.Context; +import haxe.macro.Expr; +using StringTools; /** * Macro used in the options class to add getters for the SOLO keybinds. diff --git a/source/funkin/backend/system/macros/Utils.hx b/source/funkin/backend/system/macros/Utils.hx index f55797d2..df25030c 100644 --- a/source/funkin/backend/system/macros/Utils.hx +++ b/source/funkin/backend/system/macros/Utils.hx @@ -1,7 +1,8 @@ package funkin.backend.system.macros; #if macro -import haxe.macro.Expr.ExprDef; +import haxe.macro.Context; +import haxe.macro.Expr; #end class Utils { diff --git a/source/funkin/backend/system/macros/import.hx b/source/funkin/backend/system/macros/import.hx deleted file mode 100644 index 670edbee..00000000 --- a/source/funkin/backend/system/macros/import.hx +++ /dev/null @@ -1,4 +0,0 @@ -#if macro -import haxe.macro.*; -import haxe.macro.Expr; -#end \ No newline at end of file diff --git a/source/funkin/backend/system/updating/AsyncUpdater.hx b/source/funkin/backend/system/updating/AsyncUpdater.hx index ce119a5a..52b59766 100644 --- a/source/funkin/backend/system/updating/AsyncUpdater.hx +++ b/source/funkin/backend/system/updating/AsyncUpdater.hx @@ -185,8 +185,7 @@ class UpdaterProgress { public function new() {} } -@:enum -abstract UpdaterStep(Int) { +enum abstract UpdaterStep(Int) { var PREPARING = 0; var DOWNLOADING_ASSETS = 1; var DOWNLOADING_EXECUTABLE = 2; diff --git a/source/funkin/backend/utils/AudioAnalyzer.hx b/source/funkin/backend/utils/AudioAnalyzer.hx index 235f227f..b5208fa3 100644 --- a/source/funkin/backend/utils/AudioAnalyzer.hx +++ b/source/funkin/backend/utils/AudioAnalyzer.hx @@ -15,9 +15,9 @@ class AudioAnalyzer { __peakByte = Math.pow(2, buffer.bitsPerSample-1)-1; - __timeMulti = 1 / (1 / buffer.sampleRate); - __timeMulti *= buffer.bitsPerSample; - __timeMulti -= __timeMulti % buffer.bitsPerSample; + __timeMulti = 1 / (1 / buffer.sampleRate); + __timeMulti *= buffer.bitsPerSample; + __timeMulti -= __timeMulti % buffer.bitsPerSample; } public function analyze(startPos:Float, endPos:Float):Float { @@ -25,16 +25,16 @@ class AudioAnalyzer { var bytesEndPos:Int = Math.floor(endPos * __timeMulti / 4000 / buffer.bitsPerSample) * buffer.bitsPerSample; bytesStartPos -= bytesStartPos % buffer.bitsPerSample; - bytesEndPos -= bytesEndPos % buffer.bitsPerSample; + bytesEndPos -= bytesEndPos % buffer.bitsPerSample; var maxByte:Int = 0; for(i in 0...Math.floor((bytesEndPos - bytesStartPos) / buffer.bitsPerSample)) { - var byte:Int = buffer.data.buffer.get(bytesStartPos + (i * buffer.bitsPerSample)) + var byte:Int = buffer.data.buffer.get(bytesStartPos + (i * buffer.bitsPerSample)) | (buffer.data.buffer.get(bytesStartPos + (i * buffer.bitsPerSample) + 1) << 8); if (byte > 256 * 128) byte -= 256 * 256; if (maxByte < byte) maxByte = byte; } - - return maxByte/__peakByte; + + return maxByte/__peakByte; } } \ No newline at end of file diff --git a/source/funkin/backend/utils/CoolUtil.hx b/source/funkin/backend/utils/CoolUtil.hx index 67d0b4c0..261e85f7 100644 --- a/source/funkin/backend/utils/CoolUtil.hx +++ b/source/funkin/backend/utils/CoolUtil.hx @@ -1,7 +1,6 @@ package funkin.backend.utils; import flixel.text.FlxText; -import openfl.text.TextFormatAlign; import funkin.backend.utils.XMLUtil.TextFormat; import flixel.tweens.FlxTween; import flixel.system.frontEnds.SoundFrontEnd; @@ -9,7 +8,6 @@ import flixel.sound.FlxSound; import funkin.backend.system.Conductor; import flixel.sound.FlxSoundGroup; import haxe.Json; -import funkin.menus.StoryMenuState.WeekData; import haxe.io.Path; import haxe.xml.Access; import flixel.input.keyboard.FlxKey; @@ -17,10 +15,7 @@ import lime.utils.Assets; import flixel.animation.FlxAnimation; import flixel.util.FlxColor; import flixel.util.FlxAxes; -import flixel.graphics.frames.FlxFrame; -import flixel.graphics.frames.FlxFramesCollection; import openfl.geom.ColorTransform; -import funkin.backend.chart.Chart; import haxe.CallStack; using StringTools; diff --git a/source/funkin/backend/utils/NativeAPI.hx b/source/funkin/backend/utils/NativeAPI.hx index 061021bc..a651645e 100644 --- a/source/funkin/backend/utils/NativeAPI.hx +++ b/source/funkin/backend/utils/NativeAPI.hx @@ -3,8 +3,8 @@ package funkin.backend.utils; import funkin.backend.utils.native.*; /** - * Class for Windows-only functions, such as transparent windows, message boxes, and more. - * Does not have any effect on other platforms. + * Class for functions that talk to a lower level than haxe, such as message boxes, and more. + * Some functions might not have effect on some platforms. */ class NativeAPI { @:dox(hide) public static function registerAudio() { diff --git a/source/funkin/backend/utils/native/Windows.hx b/source/funkin/backend/utils/native/Windows.hx index 1efb4d33..07312d8d 100644 --- a/source/funkin/backend/utils/native/Windows.hx +++ b/source/funkin/backend/utils/native/Windows.hx @@ -1,7 +1,7 @@ package funkin.backend.utils.native; -import funkin.backend.utils.NativeAPI.MessageBoxIcon; #if windows +import funkin.backend.utils.NativeAPI.MessageBoxIcon; @:buildXml(' @@ -12,7 +12,7 @@ import funkin.backend.utils.NativeAPI.MessageBoxIcon; ') -// majority is taken from microsofts doc +// majority is taken from microsofts doc @:cppFileCode(' #include "mmdeviceapi.h" #include "combaseapi.h" @@ -36,7 +36,7 @@ static long lastDefId = 0; class AudioFixClient : public IMMNotificationClient { LONG _cRef; IMMDeviceEnumerator *_pEnumerator; - + public: AudioFixClient() : _cRef(1), @@ -153,9 +153,9 @@ class Windows { public static function allocConsole() { } - + @:functionCode(' - HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE); + HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(console, color); ') public static function setConsoleColors(color:Int) { @@ -175,7 +175,7 @@ class Windows { MessageBox(GetActiveWindow(), message, caption, icon | MB_SETFOREGROUND); ') public static function showMessageBox(caption:String, message:String, icon:MessageBoxIcon = MSG_WARNING) { - + } @:functionCode(' diff --git a/source/funkin/editors/EditorPicker.hx b/source/funkin/editors/EditorPicker.hx index 1ddbd508..7056305f 100644 --- a/source/funkin/editors/EditorPicker.hx +++ b/source/funkin/editors/EditorPicker.hx @@ -1,6 +1,5 @@ package funkin.editors; -import flixel.addons.transition.FlxTransitionableState; import flixel.math.FlxPoint; import flixel.effects.FlxFlicker; diff --git a/source/funkin/editors/SaveSubstate.hx b/source/funkin/editors/SaveSubstate.hx index aed0c120..6250050a 100644 --- a/source/funkin/editors/SaveSubstate.hx +++ b/source/funkin/editors/SaveSubstate.hx @@ -5,9 +5,6 @@ import sys.io.File; #end import haxe.io.Path; import lime.ui.FileDialog; -import openfl.net.FileReference; -import openfl.events.Event; -import openfl.events.IOErrorEvent; class SaveSubstate extends MusicBeatSubstate { public var saveOptions:Map; diff --git a/source/funkin/editors/character/CharacterEditor.hx b/source/funkin/editors/character/CharacterEditor.hx index 24166263..25c2d33b 100644 --- a/source/funkin/editors/character/CharacterEditor.hx +++ b/source/funkin/editors/character/CharacterEditor.hx @@ -5,9 +5,7 @@ import haxe.xml.Printer; import haxe.xml.Access; import funkin.backend.utils.XMLUtil.AnimData; import flixel.math.FlxPoint; -import flixel.animation.FlxAnimation; import funkin.editors.ui.UIContextMenu.UIContextMenuOption; -import flixel.input.keyboard.FlxKey; import funkin.game.Character; class CharacterEditor extends UIState { diff --git a/source/funkin/editors/charter/ChartCreationScreen.hx b/source/funkin/editors/charter/ChartCreationScreen.hx index 46a68488..c89835f9 100644 --- a/source/funkin/editors/charter/ChartCreationScreen.hx +++ b/source/funkin/editors/charter/ChartCreationScreen.hx @@ -3,7 +3,6 @@ package funkin.editors.charter; import flixel.text.FlxText.FlxTextFormat; import flixel.text.FlxText.FlxTextFormatMarkerPair; import funkin.backend.shaders.CustomShader; -import flixel.math.FlxRect; import funkin.game.Character; import funkin.game.Stage; import funkin.game.HealthIcon; diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx index 083634c6..38023cfc 100644 --- a/source/funkin/editors/charter/Charter.hx +++ b/source/funkin/editors/charter/Charter.hx @@ -1,7 +1,5 @@ package funkin.editors.charter; -import openfl.geom.Rectangle; -import flixel.util.FlxSpriteUtil; import funkin.editors.ui.UIContextMenu.UIContextMenuOptionSpr; import funkin.editors.ui.UITopMenu.UITopMenuButton; import funkin.editors.charter.CharterStrumline; @@ -10,20 +8,14 @@ import funkin.backend.system.framerate.Framerate; import haxe.Json; import flixel.input.keyboard.FlxKey; import flixel.sound.FlxSound; -import flixel.util.FlxSort; import flixel.math.FlxPoint; import funkin.editors.charter.CharterBackdropGroup.CharterBackdropDummy; import funkin.backend.system.Conductor; import funkin.backend.chart.*; import funkin.backend.chart.ChartData; -import openfl.display.BitmapData; -import flixel.util.FlxColor; import flixel.addons.display.FlxBackdrop; import funkin.editors.ui.UIContextMenu.UIContextMenuOption; import funkin.editors.ui.UIState; -import openfl.net.FileReference; - -using flixel.util.FlxColor; class Charter extends UIState { public static var __song:String; @@ -59,7 +51,7 @@ class Charter extends UIState { public var addEventSpr:CharterEventAdd; public var gridBackdropDummy:CharterBackdropDummy; - public var noteHoverer:CharterNote; + public var noteHoverer:CharterNoteHoverer; public var strumlineInfoBG:FlxSprite; public var strumlineAddButton:CharterStrumlineButton; @@ -549,7 +541,6 @@ class Charter extends UIState { for(e in eventsGroup.members) e.refreshEventIcons(); - buildNoteTypesUI(); refreshBPMSensitive(); @@ -580,47 +571,45 @@ class Charter extends UIState { * NOTE AND CHARTER GRID LOGIC HERE */ #if REGION - var gridActionType:CharterGridActionType = NONE; - var dragStartPos:FlxPoint = new FlxPoint(); - var selectionDragging:Bool = false; + public var gridActionType:CharterGridActionType = NONE; + public var dragStartPos:FlxPoint = new FlxPoint(); + public var mousePos:FlxPoint = new FlxPoint(); + public var selectionDragging:Bool = false; + + public function updateSelectionLogic() { + function select(s:ICharterSelectable) { + if (FlxG.keys.pressed.CONTROL) selection.push(s); + else if (FlxG.keys.pressed.SHIFT) selection.remove(s); + else selection = [s]; + } - public function updateNoteLogic(elapsed:Float) { for (group in [notesGroup, eventsGroup]) { - cast(group, FlxTypedGroup).forEach(function(n) { - n.selected = false; - if (n.hovered && gridActionType == NONE) { - if (FlxG.mouse.justReleased) { - if (FlxG.keys.pressed.CONTROL) - selection.push(cast n); - else if (FlxG.keys.pressed.SHIFT) - selection.remove(cast n); - else - selection = [cast n]; - } - - if (FlxG.mouse.justReleasedRight) { - var mousePos = FlxG.mouse.getScreenPosition(uiCamera); - if (!selection.contains(cast n)) - selection = [cast n]; - closeCurrentContextMenu(); - openContextMenu(topMenu[1].childs, null, mousePos.x, mousePos.y); - mousePos.put(); - } + cast(group, FlxTypedGroup).forEach(function(s) { + s.selected = false; + if (gridActionType == NONE) { + if (s is CharterNote) { + var n:CharterNote = cast s; + if ((n.hovered || n.sustainDraggable) && FlxG.mouse.justReleased) select(cast s); + } else if (FlxG.mouse.justReleased && s.hovered) select(cast s); } }); } selection = __fixSelection(selection); for(s in selection) s.selected = true; + } + + public function updateNoteLogic(elapsed:Float) { + updateSelectionLogic(); /** * NOTE DRAG HANDLING */ - var mousePos = FlxG.mouse.getWorldPosition(charterCamera); + mousePos = FlxG.mouse.getWorldPosition(charterCamera); if (!gridBackdropDummy.hoveredByChild && !FlxG.mouse.pressed) gridActionType = NONE; selectionBox.visible = false; switch(gridActionType) { - case BOX: + case BOX_SELECTION: if (gridBackdropDummy.hoveredByChild) { selectionBox.visible = true; if (FlxG.mouse.pressed) { @@ -655,7 +644,7 @@ class Charter extends UIState { // do nothing, locked if (!FlxG.mouse.pressed) gridActionType = NONE; - case DRAG: + case NOTE_DRAG: selectionDragging = FlxG.mouse.pressed; if (selectionDragging) { gridBackdrops.draggingObj = null; @@ -718,7 +707,7 @@ class Charter extends UIState { if (gridBackdropDummy.hovered) { // AUTO DETECT if (FlxG.mouse.pressed && (Math.abs(mousePos.x - dragStartPos.x) > 20 || Math.abs(mousePos.y - dragStartPos.y) > 20)) - gridActionType = BOX; + gridActionType = BOX_SELECTION; var id = Math.floor(mousePos.x / 40); var mouseOnGrid = id >= 0 && id < 4 * gridBackdrops.strumlinesAmount && mousePos.y >= 0; @@ -739,14 +728,21 @@ class Charter extends UIState { } } } else if (gridBackdropDummy.hoveredByChild) { - if (FlxG.mouse.pressed && (Math.abs(mousePos.x - dragStartPos.x) > 5 || Math.abs(mousePos.y - dragStartPos.y) > 5)) { + if (FlxG.mouse.pressed) { var noteHovered:Bool = false; - for(n in selection) - if (n.hovered) { - noteHovered = true; - break; - } - gridActionType = noteHovered ? DRAG : INVALID_DRAG; + for(n in selection) if (n.hovered) {noteHovered = true; break;} + + var noteSusDrag:Bool = false; + for(s in selection) { + if (!(s is CharterNote)) continue; + var n:CharterNote = cast s; + if (n.sustainDraggable) {noteSusDrag = true; break;} + } + + if ((Math.abs(mousePos.x - dragStartPos.x) > (noteSusDrag ? 1 : 5) || Math.abs(mousePos.y - dragStartPos.y) > (noteSusDrag ? 1 : 5))) { + if (noteHovered) gridActionType = noteHovered ? NOTE_DRAG : INVALID_DRAG; + if (noteSusDrag) gridActionType = SUSTAIN_DRAG; + } } } @@ -756,6 +752,35 @@ class Charter extends UIState { openContextMenu(topMenu[1].childs, null, mousePos.x, mousePos.y); mousePos.put(); } + case SUSTAIN_DRAG: + selectionDragging = FlxG.mouse.pressed; + if (selectionDragging) { + currentCursor = BUTTON; + selection.loop(function (n:CharterNote) { + var change:Float = Math.max((mousePos.y-(FlxG.keys.pressed.SHIFT ? dragStartPos.y : quantStep(dragStartPos.y))) / 40, -n.susLength); + n.tempSusLength = change; + + if (!FlxG.keys.pressed.SHIFT) + n.tempSusLength -= (n.susLength + change) - quantStepRounded(n.susLength + change, change > 0 ? 0.35 : 0.65); + @:privateAccess n.__susInstaLerp = FlxG.keys.pressed.SHIFT; + }); + } else { + var undoChanges:Array = []; + selection.loop(function (n:CharterNote) { + var oldSusLen:Float = n.susLength; + + n.susLength += n.tempSusLength; + n.tempSusLength = 0; + + @:privateAccess n.__susInstaLerp = false; + n.updatePos(n.step, n.id, n.susLength, n.type); + undoChanges.push({before: oldSusLen, after: n.susLength, note: n}); + }); + undos.addToUndo(CEditSustains(undoChanges)); + + gridActionType = NONE; + currentCursor = ARROW; + } } addEventSpr.selectable = !selectionBox.visible; @@ -769,6 +794,8 @@ class Charter extends UIState { if (event != null) addEventSpr.updateEdit(event); else addEventSpr.updatePos(FlxG.keys.pressed.SHIFT ? ((mousePos.y) / 40) : quantStepRounded(mousePos.y/40)); } else addEventSpr.sprAlpha = lerp(addEventSpr.sprAlpha, 0, 0.25); + + noteHoverer.showHoverer = Charter.instance.gridBackdropDummy.hovered; } public function quantStep(step:Float):Float { @@ -1475,7 +1502,7 @@ class Charter extends UIState { if (s is CharterNote) { var n:CharterNote = cast s; var old:Float = n.susLength; - n.updatePos(n.step, n.id, Math.max(n.susLength + change, 0)); + n.updatePos(n.step, n.id, Math.max(n.susLength + change, 0), n.type); undoChanges.push({before: old, after: n.susLength, note: n}); } @@ -1783,9 +1810,10 @@ interface ICharterSelectable { enum abstract CharterGridActionType(Int) { var NONE = 0; - var BOX = 1; - var DRAG = 2; + var BOX_SELECTION = 1; + var NOTE_DRAG = 2; var INVALID_DRAG = 3; + var SUSTAIN_DRAG = 4; } typedef PlaytestInfo = { diff --git a/source/funkin/editors/charter/CharterBackdropGroup.hx b/source/funkin/editors/charter/CharterBackdropGroup.hx index 7e69b7e9..f99571ab 100644 --- a/source/funkin/editors/charter/CharterBackdropGroup.hx +++ b/source/funkin/editors/charter/CharterBackdropGroup.hx @@ -1,6 +1,5 @@ package funkin.editors.charter; -import flixel.util.FlxPool; import flixel.graphics.FlxGraphic; import funkin.backend.system.Conductor; import openfl.geom.Rectangle; diff --git a/source/funkin/editors/charter/CharterNote.hx b/source/funkin/editors/charter/CharterNote.hx index 0a9af564..1ea7804d 100644 --- a/source/funkin/editors/charter/CharterNote.hx +++ b/source/funkin/editors/charter/CharterNote.hx @@ -9,6 +9,9 @@ import flixel.util.FlxColor; class CharterNote extends UISprite implements ICharterSelectable { var angleTween:FlxTween; + var __doAnim:Bool = false; + var __animSpeed:Float = 1; + var __susInstaLerp:Bool = false; private static var colors:Array = [ 0xFFC24B99, @@ -17,10 +20,11 @@ class CharterNote extends UISprite implements ICharterSelectable { 0xFFF9393F ]; - public var sustainSpr:FlxSprite; + public var sustainSpr:UISprite; + public var tempSusLength:Float = 0; + public var sustainDraggable:Bool = false; + public var typeText:UIText; - var __doAnim:Bool = false; - var __animSpeed:Float = 1; public var selected:Bool = false; public var draggable:Bool = true; @@ -34,15 +38,15 @@ class CharterNote extends UISprite implements ICharterSelectable { animation.play("note"); this.setUnstretchedGraphicSize(40, 40, false); - cursor = BUTTON; - moves = false; - - sustainSpr = new FlxSprite(10, 40); - sustainSpr.makeGraphic(1, 1, -1); + sustainSpr = new UISprite(10, 20); + sustainSpr.makeSolid(1, 1, -1); + sustainSpr.scale.set(10, 0); members.push(sustainSpr); typeText = new UIText(x, y, 0, Std.string(type)); - //typeText.borderSize = 1.5; + + cursor = sustainSpr.cursor = BUTTON; + moves = false; } public override function updateButtonHandler() { @@ -82,12 +86,6 @@ class CharterNote extends UISprite implements ICharterSelectable { y = step * 40; - sustainSpr.scale.set(10, (40 * susLength) + (height/2)); - sustainSpr.updateHitbox(); - sustainSpr.exists = susLength != 0; - sustainSpr.alpha = alpha; - sustainSpr.follow(this, 15, 20); - if (angleTween != null) angleTween.cancel(); var destAngle = switch(animation.curAnim.curFrame = (id % 4)) { @@ -134,8 +132,18 @@ class CharterNote extends UISprite implements ICharterSelectable { var __passed:Bool = false; public override function update(elapsed:Float) { super.update(elapsed); - if (sustainSpr.exists) - sustainSpr.follow(this, 15, 20); + + var sprLength:Float = (40 * (susLength+tempSusLength)) + ((susLength+tempSusLength) != 0 ? (height/2) : 0); + sustainSpr.scale.set(10, __susInstaLerp ? sprLength : CoolUtil.fpsLerp(sustainSpr.scale.y, sprLength, 1/2)); + sustainSpr.updateHitbox(); + sustainSpr.follow(this, 15, 20); + + sustainDraggable = false; + if (!hovered && susLength != 0) { + UIState.state.updateSpriteRect(sustainSpr); + sustainDraggable = UIState.state.isOverlapping(sustainSpr, @:privateAccess sustainSpr.__rect); + } + if (typeText.exists) typeText.follow(this, 20 - (typeText.frameWidth/2), 20 - (typeText.frameHeight/2)); diff --git a/source/funkin/editors/charter/CharterNoteHoverer.hx b/source/funkin/editors/charter/CharterNoteHoverer.hx index e3648daf..46997a9b 100644 --- a/source/funkin/editors/charter/CharterNoteHoverer.hx +++ b/source/funkin/editors/charter/CharterNoteHoverer.hx @@ -1,6 +1,8 @@ package funkin.editors.charter; class CharterNoteHoverer extends CharterNote { + public var showHoverer:Bool = false; + public function new() { super(); @@ -15,7 +17,7 @@ class CharterNoteHoverer extends CharterNote { switch (Charter.instance.gridActionType) { case NONE: var inBoundsY:Bool = (__mousePos.y > 0 && __mousePos.y < (Charter.instance.__endStep)*40); - if (__mousePos.x > 0 && __mousePos.x < Charter.instance.gridBackdrops.strumlinesAmount * 160 && inBoundsY) { + if ((__mousePos.x > 0 && __mousePos.x < Charter.instance.gridBackdrops.strumlinesAmount * 160 && inBoundsY) && showHoverer) { step = FlxMath.bound(FlxG.keys.pressed.SHIFT ? ((__mousePos.y-20) / 40) : Charter.instance.quantStep(__mousePos.y/40), 0, Charter.instance.__endStep-1); id = Math.floor(__mousePos.x / 40); y = step * 40; x = id * 40; visible = true; sustainSpr.visible = typeText.visible = false; angle = switch(animation.curAnim.curFrame = (id % 4)) { @@ -27,7 +29,7 @@ class CharterNoteHoverer extends CharterNote { }; } else visible = false; - case DRAG: + case NOTE_DRAG: visible = sustainSpr.visible = typeText.visible = true; __doAnim = false; default: visible = sustainSpr.visible = typeText.visible = false; __doAnim = false; @@ -38,8 +40,8 @@ class CharterNoteHoverer extends CharterNote { switch (Charter.instance.gridActionType) { case NONE: super.draw(); - case DRAG: - if (Charter.instance.gridActionType == DRAG) { + case NOTE_DRAG: + if (Charter.instance.gridActionType == NOTE_DRAG) { var verticalChange:Float = (__mousePos.y - Charter.instance.dragStartPos.y) / 40; var horizontalChange:Int = CoolUtil.floorInt((__mousePos.x - (Std.int(Charter.instance.dragStartPos.x / 40) * 40)) / 40); diff --git a/source/funkin/editors/charter/CharterSelection.hx b/source/funkin/editors/charter/CharterSelection.hx index 7835603a..ba1acdc4 100644 --- a/source/funkin/editors/charter/CharterSelection.hx +++ b/source/funkin/editors/charter/CharterSelection.hx @@ -3,11 +3,9 @@ package funkin.editors.charter; import funkin.backend.chart.ChartData; import funkin.backend.chart.ChartData.ChartMetaData; import haxe.Json; -import funkin.backend.assets.ModsFolder; import funkin.editors.charter.SongCreationScreen.SongCreationData; import funkin.options.type.NewOption; import funkin.backend.system.framerate.Framerate; -import flixel.util.FlxColor; import funkin.menus.FreeplayState.FreeplaySonglist; import funkin.editors.EditorTreeMenu; import funkin.options.*; diff --git a/source/funkin/editors/charter/CharterStrumLineGroup.hx b/source/funkin/editors/charter/CharterStrumLineGroup.hx index 3018300c..a342c779 100644 --- a/source/funkin/editors/charter/CharterStrumLineGroup.hx +++ b/source/funkin/editors/charter/CharterStrumLineGroup.hx @@ -1,6 +1,5 @@ package funkin.editors.charter; -import funkin.backend.chart.ChartData.ChartStrumLine; import funkin.backend.chart.EventsData; import flixel.util.FlxSort; diff --git a/source/funkin/editors/charter/CharterStrumline.hx b/source/funkin/editors/charter/CharterStrumline.hx index 185e4a04..bee6e7a3 100644 --- a/source/funkin/editors/charter/CharterStrumline.hx +++ b/source/funkin/editors/charter/CharterStrumline.hx @@ -1,9 +1,7 @@ package funkin.editors.charter; import flixel.group.FlxSpriteGroup; -import funkin.backend.chart.EventsData; import funkin.game.Character; -import funkin.editors.ui.UIContextMenu.UIContextMenuOption; import funkin.editors.ui.UITopMenu.UITopMenuButton; import funkin.game.HealthIcon; import funkin.backend.chart.ChartData.ChartStrumLine; diff --git a/source/funkin/editors/charter/SongCreationScreen.hx b/source/funkin/editors/charter/SongCreationScreen.hx index 0a6da065..fdd9cf1e 100644 --- a/source/funkin/editors/charter/SongCreationScreen.hx +++ b/source/funkin/editors/charter/SongCreationScreen.hx @@ -3,7 +3,7 @@ package funkin.editors.charter; import flixel.text.FlxText.FlxTextFormat; import flixel.text.FlxText.FlxTextFormatMarkerPair; import flixel.group.FlxGroup; -import funkin.backend.chart.ChartData; +import funkin.backend.chart.ChartData.ChartMetaData; import haxe.io.Bytes; typedef SongCreationData = { diff --git a/source/funkin/editors/import.hx b/source/funkin/editors/import.hx index b15a4507..75250a63 100644 --- a/source/funkin/editors/import.hx +++ b/source/funkin/editors/import.hx @@ -1,6 +1,8 @@ +#if !macro package funkin.editors; import funkin.editors.ui.*; import flixel.math.FlxPoint; -using funkin.editors.ui.UIUtil; \ No newline at end of file +using funkin.editors.ui.UIUtil; +#end \ No newline at end of file diff --git a/source/funkin/editors/ui/UIAudioPlayer.hx b/source/funkin/editors/ui/UIAudioPlayer.hx index daf6b3b2..ad1ba457 100644 --- a/source/funkin/editors/ui/UIAudioPlayer.hx +++ b/source/funkin/editors/ui/UIAudioPlayer.hx @@ -3,7 +3,6 @@ package funkin.editors.ui; import flixel.math.FlxRect; import flixel.util.FlxColor; import flixel.ui.FlxBar; -import openfl.geom.Rectangle; import flixel.sound.FlxSound; import haxe.io.Bytes; import lime.media.AudioBuffer; diff --git a/source/funkin/editors/ui/UIAutoCompleteTextBox.hx b/source/funkin/editors/ui/UIAutoCompleteTextBox.hx index 6b5d31b3..938a2384 100644 --- a/source/funkin/editors/ui/UIAutoCompleteTextBox.hx +++ b/source/funkin/editors/ui/UIAutoCompleteTextBox.hx @@ -1,10 +1,7 @@ package funkin.editors.ui; -import flixel.math.FlxPoint; import lime.ui.KeyModifier; import lime.ui.KeyCode; -import openfl.desktop.Clipboard; -import openfl.geom.Rectangle; class UIAutoCompleteTextBox extends UITextBox { public var suggestionText:UIText; diff --git a/source/funkin/editors/ui/UIButton.hx b/source/funkin/editors/ui/UIButton.hx index f3e67821..c5522c5c 100644 --- a/source/funkin/editors/ui/UIButton.hx +++ b/source/funkin/editors/ui/UIButton.hx @@ -1,7 +1,5 @@ package funkin.editors.ui; -import flixel.graphics.frames.FlxFrame; - class UIButton extends UISliceSprite { public var callback:Void->Void = null; public var field:UIText; diff --git a/source/funkin/editors/ui/UIButtonList.hx b/source/funkin/editors/ui/UIButtonList.hx index af27be84..59d88971 100644 --- a/source/funkin/editors/ui/UIButtonList.hx +++ b/source/funkin/editors/ui/UIButtonList.hx @@ -1,10 +1,7 @@ package funkin.editors.ui; import flixel.FlxCamera; -import flixel.group.FlxGroup; -import flixel.util.FlxColor; import flixel.math.FlxPoint; -import funkin.game.Character; import flixel.util.FlxSort; import flixel.math.FlxMath; diff --git a/source/funkin/editors/ui/UICheckbox.hx b/source/funkin/editors/ui/UICheckbox.hx index 8a0b1a55..a5bcdef3 100644 --- a/source/funkin/editors/ui/UICheckbox.hx +++ b/source/funkin/editors/ui/UICheckbox.hx @@ -1,7 +1,5 @@ package funkin.editors.ui; -import funkin.backend.FunkinText; - class UICheckbox extends UISprite { public var checked:Bool = false; public var onChecked:Bool->Void = null; diff --git a/source/funkin/editors/ui/UIState.hx b/source/funkin/editors/ui/UIState.hx index b43e605e..3e33004e 100644 --- a/source/funkin/editors/ui/UIState.hx +++ b/source/funkin/editors/ui/UIState.hx @@ -2,7 +2,6 @@ package funkin.editors.ui; import lime.ui.KeyModifier; import lime.ui.KeyCode; -import openfl.events.KeyboardEvent; import funkin.backend.system.framerate.Framerate; import funkin.editors.ui.UIContextMenu.UIContextMenuCallback; import openfl.ui.Mouse; diff --git a/source/funkin/game/GameOverSubstate.hx b/source/funkin/game/GameOverSubstate.hx index c7d6c44e..3d119f02 100644 --- a/source/funkin/game/GameOverSubstate.hx +++ b/source/funkin/game/GameOverSubstate.hx @@ -4,10 +4,7 @@ import funkin.editors.charter.Charter; import funkin.backend.scripting.events.GameOverCreationEvent; import funkin.backend.scripting.events.CancellableEvent; import funkin.backend.scripting.Script; -import flixel.addons.transition.FlxTransitionableState; import flixel.sound.FlxSound; -import flixel.FlxSubState; -import flixel.math.FlxPoint; import flixel.util.FlxColor; import flixel.util.FlxTimer; import funkin.menus.StoryMenuState; diff --git a/source/funkin/game/HudCamera.hx b/source/funkin/game/HudCamera.hx index c0b6c48e..accd5f30 100644 --- a/source/funkin/game/HudCamera.hx +++ b/source/funkin/game/HudCamera.hx @@ -1,31 +1,7 @@ package funkin.game; - -import lime.app.Application; -import flixel.graphics.tile.FlxGraphicsShader; -import openfl.display.Bitmap; -import openfl.display.BitmapData; -import openfl.display.DisplayObject; -import openfl.display.Graphics; -import openfl.display.Sprite; -import openfl.geom.ColorTransform; -import openfl.geom.Point; -import openfl.geom.Rectangle; -import flixel.graphics.FlxGraphic; -import flixel.graphics.frames.FlxFrame; -import flixel.graphics.tile.FlxDrawBaseItem; -import flixel.graphics.tile.FlxDrawTrianglesItem; import flixel.math.FlxMatrix; import flixel.math.FlxPoint; -import flixel.math.FlxRect; -import flixel.system.FlxAssets.FlxShader; -import flixel.util.FlxAxes; -import flixel.util.FlxColor; -import flixel.util.FlxSpriteUtil; -import openfl.display.BlendMode; -import openfl.filters.BitmapFilter; -import openfl.filters.ShaderFilter; -import openfl.Vector; class HudCamera extends FlxCamera { public var downscroll:Bool = false; diff --git a/source/funkin/game/Note.hx b/source/funkin/game/Note.hx index e72d62ec..b8baf48e 100644 --- a/source/funkin/game/Note.hx +++ b/source/funkin/game/Note.hx @@ -1,11 +1,8 @@ package funkin.game; -import funkin.backend.chart.Chart; import funkin.backend.chart.ChartData; -import flixel.graphics.frames.FlxAtlasFrames; -import flixel.util.FlxColor; -import flixel.math.FlxRect; import flixel.math.FlxPoint; +import flixel.math.FlxRect; import funkin.backend.system.Conductor; import funkin.backend.scripting.events.*; diff --git a/source/funkin/game/PlayState.hx b/source/funkin/game/PlayState.hx index 575c612c..c567b3c5 100644 --- a/source/funkin/game/PlayState.hx +++ b/source/funkin/game/PlayState.hx @@ -2,7 +2,6 @@ package funkin.game; import funkin.editors.charter.CharterSelection; import flixel.FlxState; -import funkin.editors.EditorTreeMenu; import funkin.editors.SaveWarning; import funkin.backend.chart.EventsData; import funkin.backend.system.RotatingSpriteGroup; @@ -15,11 +14,9 @@ import funkin.game.SplashHandler; import funkin.backend.scripting.DummyScript; import funkin.menus.StoryMenuState.WeekData; import funkin.backend.FunkinText; -import flixel.group.FlxSpriteGroup; import funkin.backend.scripting.Script; import funkin.backend.scripting.ScriptPack; import flixel.FlxSubState; -import flixel.addons.transition.FlxTransitionableState; import flixel.math.FlxPoint; import flixel.sound.FlxSound; import flixel.text.FlxText; @@ -762,7 +759,7 @@ class PlayState extends MusicBeatState SaveWarning.warningFunc = saveWarn; SaveWarning.saveFunc = () -> { @:privateAccess Chart.save('${Paths.getAssetsRoot()}/songs/${Charter.__song.toLowerCase()}', - PlayState.SONG, Charter.__diff.toLowerCase(), {saveMetaInChart: false}); + PlayState.SONG, Charter.__diff.toLowerCase(), {saveMetaInChart: false, saveEventsInChart: true}); } } } diff --git a/source/funkin/game/Stage.hx b/source/funkin/game/Stage.hx index 4f645a4b..af36d445 100644 --- a/source/funkin/game/Stage.hx +++ b/source/funkin/game/Stage.hx @@ -3,7 +3,6 @@ package funkin.game; import funkin.backend.scripting.events.StageXMLEvent; import funkin.backend.scripting.events.StageNodeEvent; import flixel.math.FlxPoint; -import funkin.backend.MusicBeatGroup; import flixel.FlxState; import haxe.xml.Access; import funkin.backend.system.interfaces.IBeatReceiver; diff --git a/source/funkin/menus/BetaWarningState.hx b/source/funkin/menus/BetaWarningState.hx index 78813ac0..08d60f39 100644 --- a/source/funkin/menus/BetaWarningState.hx +++ b/source/funkin/menus/BetaWarningState.hx @@ -1,6 +1,5 @@ package funkin.menus; -import flixel.addons.transition.FlxTransitionableState; import flixel.util.FlxColor; import flixel.text.FlxText; import funkin.backend.FunkinText; diff --git a/source/funkin/menus/FreeplayState.hx b/source/funkin/menus/FreeplayState.hx index b2531268..f88b8d99 100644 --- a/source/funkin/menus/FreeplayState.hx +++ b/source/funkin/menus/FreeplayState.hx @@ -1,17 +1,14 @@ package funkin.menus; import funkin.backend.chart.Chart; -import funkin.backend.chart.ChartData; +import funkin.backend.chart.ChartData.ChartMetaData; import haxe.io.Path; import openfl.text.TextField; -import flixel.FlxState; -import flixel.addons.display.FlxGridOverlay; import flixel.text.FlxText; import flixel.util.FlxColor; import lime.utils.Assets; import funkin.game.HealthIcon; import funkin.savedata.FunkinSave; -import haxe.Json; import funkin.backend.scripting.events.*; using StringTools; @@ -411,17 +408,14 @@ class FreeplayState extends MusicBeatState var event = event("onUpdateOptionsAlpha", EventManager.get(FreeplayAlphaUpdateEvent).recycle(0.6, 0.45, 1, 1, 0.25)); if (event.cancelled) return; - var bullShit:Int = 0; - for (i in 0...iconArray.length) iconArray[i].alpha = lerp(iconArray[i].alpha, #if PRELOAD_ALL songInstPlaying ? event.idlePlayingAlpha : #end event.idleAlpha, event.lerp); iconArray[curSelected].alpha = #if PRELOAD_ALL songInstPlaying ? event.selectedPlayingAlpha : #end event.selectedAlpha; - for (item in grpSongs.members) + for (i=>item in grpSongs.members) { - item.targetY = bullShit - curSelected; - bullShit++; + item.targetY = i - curSelected; item.alpha = lerp(item.alpha, #if PRELOAD_ALL songInstPlaying ? event.idlePlayingAlpha : #end event.idleAlpha, event.lerp); diff --git a/source/funkin/menus/GitarooPause.hx b/source/funkin/menus/GitarooPause.hx index bc782121..a8448b4e 100644 --- a/source/funkin/menus/GitarooPause.hx +++ b/source/funkin/menus/GitarooPause.hx @@ -1,7 +1,6 @@ package funkin.menus; import funkin.editors.charter.Charter; -import flixel.graphics.frames.FlxAtlasFrames; class GitarooPause extends MusicBeatState { diff --git a/source/funkin/menus/MainMenuState.hx b/source/funkin/menus/MainMenuState.hx index ea6a71b9..2c5c7101 100644 --- a/source/funkin/menus/MainMenuState.hx +++ b/source/funkin/menus/MainMenuState.hx @@ -4,9 +4,7 @@ import haxe.Json; import funkin.backend.FunkinText; import funkin.menus.credits.CreditsMain; import flixel.FlxState; -import flixel.addons.transition.FlxTransitionableState; import flixel.effects.FlxFlicker; -import flixel.graphics.frames.FlxAtlasFrames; import flixel.text.FlxText; import flixel.tweens.FlxTween; import flixel.util.FlxColor; diff --git a/source/funkin/menus/PauseSubState.hx b/source/funkin/menus/PauseSubState.hx index 2fe5e85a..b0c34bf9 100644 --- a/source/funkin/menus/PauseSubState.hx +++ b/source/funkin/menus/PauseSubState.hx @@ -6,9 +6,6 @@ import funkin.options.OptionsMenu; import funkin.backend.scripting.events.PauseCreationEvent; import funkin.backend.scripting.events.NameEvent; import funkin.backend.scripting.Script; -import flixel.FlxSubState; -import flixel.addons.transition.FlxTransitionableState; -import flixel.input.keyboard.FlxKey; import flixel.sound.FlxSound; import flixel.text.FlxText; import flixel.tweens.FlxTween; @@ -194,12 +191,9 @@ class PauseSubState extends MusicBeatSubstate curSelected = event.value; - var bullShit:Int = 0; - - for (item in grpMenuShit.members) + for (i=>item in grpMenuShit.members) { - item.targetY = bullShit - curSelected; - bullShit++; + item.targetY = i - curSelected; if (item.targetY == 0) item.alpha = 1; diff --git a/source/funkin/menus/StoryMenuState.hx b/source/funkin/menus/StoryMenuState.hx index 705758e0..0f8dd1d5 100644 --- a/source/funkin/menus/StoryMenuState.hx +++ b/source/funkin/menus/StoryMenuState.hx @@ -5,7 +5,6 @@ import haxe.io.Path; import funkin.backend.scripting.events.*; import flixel.util.FlxTimer; import flixel.math.FlxPoint; -import flixel.graphics.frames.FlxFramesCollection; import flixel.tweens.FlxTween; import flixel.util.FlxColor; import funkin.backend.FunkinText; @@ -37,7 +36,7 @@ class StoryMenuState extends MusicBeatState { public var weekSprites:FlxTypedGroup; public var characterSprites:FlxTypedGroup; - public var charFrames:Map = []; + //public var charFrames:Map = []; public override function create() { super.create(); diff --git a/source/funkin/menus/TitleState.hx b/source/funkin/menus/TitleState.hx index da7e25f8..a24a8e86 100644 --- a/source/funkin/menus/TitleState.hx +++ b/source/funkin/menus/TitleState.hx @@ -1,27 +1,12 @@ package funkin.menus; -import funkin.backend.system.github.GitHub; import funkin.backend.MusicBeatGroup; import funkin.backend.utils.XMLUtil; -import flixel.util.typeLimit.OneOfThree; import flixel.util.typeLimit.OneOfTwo; -import flixel.FlxState; -import flixel.addons.display.FlxGridOverlay; -import flixel.addons.transition.FlxTransitionSprite.GraphicTransTileDiamond; -import flixel.addons.transition.FlxTransitionableState; -import flixel.graphics.FlxGraphic; -import flixel.graphics.frames.FlxAtlasFrames; import flixel.group.FlxGroup; import flixel.input.gamepad.FlxGamepad; -import flixel.math.FlxPoint; -import flixel.math.FlxRect; -import flixel.sound.FlxSound; -import flixel.system.ui.FlxSoundTray; -import flixel.text.FlxText; -import flixel.tweens.FlxTween; import flixel.util.FlxColor; import flixel.util.FlxTimer; -import funkin.backend.system.Conductor; import openfl.Assets; import haxe.xml.Access; diff --git a/source/funkin/menus/credits/CreditsMain.hx b/source/funkin/menus/credits/CreditsMain.hx index af62af37..5dd16aff 100644 --- a/source/funkin/menus/credits/CreditsMain.hx +++ b/source/funkin/menus/credits/CreditsMain.hx @@ -1,6 +1,5 @@ package funkin.menus.credits; -import funkin.backend.system.github.GitHub; import funkin.options.OptionsScreen; import funkin.options.type.*; import funkin.options.TreeMenu; diff --git a/source/funkin/menus/ui/Alphabet.hx b/source/funkin/menus/ui/Alphabet.hx index cf225a38..d4c3db47 100644 --- a/source/funkin/menus/ui/Alphabet.hx +++ b/source/funkin/menus/ui/Alphabet.hx @@ -4,7 +4,6 @@ import openfl.utils.AssetLibrary; import haxe.xml.Access; import funkin.backend.assets.LimeLibrarySymbol; import funkin.backend.assets.IModsAssetLibrary; -import flixel.graphics.frames.FlxAtlasFrames; import flixel.group.FlxSpriteGroup; import flixel.util.FlxTimer; import flixel.util.FlxColor; diff --git a/source/funkin/options/Options.hx b/source/funkin/options/Options.hx index 1104bae7..3f27a109 100644 --- a/source/funkin/options/Options.hx +++ b/source/funkin/options/Options.hx @@ -1,6 +1,5 @@ package funkin.options; -import funkin.backend.system.Controls; import openfl.Lib; import flixel.util.FlxSave; import flixel.input.keyboard.FlxKey; diff --git a/source/funkin/options/OptionsMenu.hx b/source/funkin/options/OptionsMenu.hx index 186e3249..e8226a9b 100644 --- a/source/funkin/options/OptionsMenu.hx +++ b/source/funkin/options/OptionsMenu.hx @@ -3,9 +3,6 @@ package funkin.options; import funkin.backend.system.framerate.Framerate; import funkin.options.type.Checkbox; import haxe.xml.Access; -import flixel.tweens.FlxTween; -import funkin.menus.MainMenuState; -import flixel.util.typeLimit.OneOfTwo; import funkin.options.type.*; import funkin.options.categories.*; import funkin.options.TreeMenu; diff --git a/source/funkin/options/OptionsTree.hx b/source/funkin/options/OptionsTree.hx index 2ef66408..ae4d599c 100644 --- a/source/funkin/options/OptionsTree.hx +++ b/source/funkin/options/OptionsTree.hx @@ -3,10 +3,9 @@ package funkin.options; class OptionsTree extends FlxTypedGroup { public var lastMenu:OptionsScreen; public var treeParent:TreeMenu; - public override function new() { - super(); - - } + //public override function new() { + // super(); + //} public override function update(elapsed:Float) { var last = members.last(); diff --git a/source/funkin/options/PlayerSettings.hx b/source/funkin/options/PlayerSettings.hx index 1a8750cb..5c6dc9b5 100644 --- a/source/funkin/options/PlayerSettings.hx +++ b/source/funkin/options/PlayerSettings.hx @@ -29,9 +29,6 @@ class PlayerSettings public var controls:Controls; #end - // public var avatar:Player; - // public var camera(get, never):PlayCamera; - function new(id, scheme) { this.id = id; @@ -42,7 +39,7 @@ class PlayerSettings { controls.setKeyboardScheme(scheme); } - + static public function init():Void { if (solo == null) diff --git a/source/funkin/options/TreeMenu.hx b/source/funkin/options/TreeMenu.hx index a136a03f..ac027134 100644 --- a/source/funkin/options/TreeMenu.hx +++ b/source/funkin/options/TreeMenu.hx @@ -5,10 +5,8 @@ import flixel.FlxState; import funkin.backend.FunkinText; import flixel.tweens.FlxTween; import funkin.menus.MainMenuState; -import funkin.options.type.TextOption; import flixel.util.typeLimit.OneOfTwo; import funkin.options.type.OptionType; -import funkin.options.categories.*; class TreeMenu extends UIState { public var main:OptionsScreen; diff --git a/source/funkin/options/categories/AppearanceOptions.hx b/source/funkin/options/categories/AppearanceOptions.hx index 155179ef..92621343 100644 --- a/source/funkin/options/categories/AppearanceOptions.hx +++ b/source/funkin/options/categories/AppearanceOptions.hx @@ -48,9 +48,8 @@ class AppearanceOptions extends OptionsScreen { "If checked, switching windows will pause the game.", "autoPause")); } - - private function __changeFPS(change:Float) - { + + private function __changeFPS(change:Float) { // if statement cause of the flixel warning if(FlxG.updateFramerate < Std.int(change)) FlxG.drawFramerate = FlxG.updateFramerate = Std.int(change); diff --git a/source/funkin/options/categories/GameplayOptions.hx b/source/funkin/options/categories/GameplayOptions.hx index 1db039a5..15c0ba60 100644 --- a/source/funkin/options/categories/GameplayOptions.hx +++ b/source/funkin/options/categories/GameplayOptions.hx @@ -1,9 +1,13 @@ package funkin.options.categories; +import flixel.util.FlxTimer; import funkin.backend.system.Conductor; class GameplayOptions extends OptionsScreen { var __metronome = FlxG.sound.load(Paths.sound('editors/charter/metronome')); + + var offsetSetting:NumOption; + public override function new() { super("Gameplay", 'Change Gameplay options such as Downscroll, Scroll Speed, Naughtyness...'); add(new Checkbox( @@ -14,7 +18,7 @@ class GameplayOptions extends OptionsScreen { "Ghost Tapping", "If unchecked, trying to hit any strum that have no note that can be hit will cause a miss.", "ghostTapping")); - add(new NumOption( + add(offsetSetting = new NumOption( "Song Offset", "Changes the offset that songs should start with.", -999, // minimum @@ -31,23 +35,39 @@ class GameplayOptions extends OptionsScreen { "If unchecked, will stop the camera from zooming in every 4 beats", "camZoomOnBeat")); } - private function __changeOffset(offset) Conductor.songOffset = offset; + + private function __changeOffset(offset) + Conductor.songOffset = offset; + var __lastBeat:Int = 0; var __lastSongBeat:Int = 0; + override function update(elapsed) { super.update(elapsed); FlxG.camera.zoom = CoolUtil.fpsLerp(FlxG.camera.zoom, 1, 0.04); - if (members[2].selected) { + + if (offsetSetting.selected) { FlxG.sound.music.volume = 0.5; if (__lastBeat != Conductor.curBeat) { FlxG.camera.zoom += 0.03; __lastBeat = Conductor.curBeat; } - if (__lastSongBeat != Math.floor(Conductor.getStepForTime(FlxG.sound.music.time) / Conductor.stepsPerBeat)) { + + var beat = Math.floor(Conductor.getStepForTime(FlxG.sound.music.time) / Conductor.stepsPerBeat); + if (__lastSongBeat != beat) { __metronome.replay(); - __lastSongBeat = Math.floor(Conductor.getStepForTime(FlxG.sound.music.time) / Conductor.stepsPerBeat); + __lastSongBeat = beat; } } else FlxG.sound.music.volume = 1; } + + public override function close() { + // To remove this timer move super.update(elapsed); to the end, but im afraid it will cause stuff to break + new FlxTimer().start(0.0000001, (_) -> { + FlxG.camera.zoom = 1; + FlxG.sound.music.volume = 1; + }); + super.close(); + } } \ No newline at end of file diff --git a/source/funkin/options/categories/import.hx b/source/funkin/options/categories/import.hx index 046ac6ef..49bf382e 100644 --- a/source/funkin/options/categories/import.hx +++ b/source/funkin/options/categories/import.hx @@ -1,3 +1,5 @@ +#if !macro package funkin.options.categories; -import funkin.options.type.*; \ No newline at end of file +import funkin.options.type.*; +#end \ No newline at end of file diff --git a/source/funkin/options/keybinds/ChangeKeybindSubState.hx b/source/funkin/options/keybinds/ChangeKeybindSubState.hx index 57a01e24..94c8f6bf 100644 --- a/source/funkin/options/keybinds/ChangeKeybindSubState.hx +++ b/source/funkin/options/keybinds/ChangeKeybindSubState.hx @@ -1,9 +1,5 @@ package funkin.options.keybinds; -import flixel.effects.FlxFlicker; -import funkin.backend.system.Controls; -import flixel.addons.transition.FlxTransitionableState; -import flixel.util.FlxColor; import flixel.input.keyboard.FlxKey; class ChangeKeybindSubState extends MusicBeatSubstate { @@ -27,7 +23,7 @@ class ChangeKeybindSubState extends MusicBeatSubstate { if (cast(key, Int) <= 0) return; if (key == ESCAPE && !FlxG.keys.pressed.SHIFT) { - close(); + close(); cancelCallback(); return; } diff --git a/source/funkin/options/keybinds/KeybindSetting.hx b/source/funkin/options/keybinds/KeybindSetting.hx index 37dd9913..3fa1a9fc 100644 --- a/source/funkin/options/keybinds/KeybindSetting.hx +++ b/source/funkin/options/keybinds/KeybindSetting.hx @@ -1,9 +1,6 @@ package funkin.options.keybinds; import flixel.effects.FlxFlicker; -import funkin.backend.system.Controls; -import flixel.addons.transition.FlxTransitionableState; -import flixel.util.FlxColor; import flixel.input.keyboard.FlxKey; using StringTools; diff --git a/source/funkin/options/keybinds/KeybindsOptions.hx b/source/funkin/options/keybinds/KeybindsOptions.hx index 9176d27b..cb974c47 100644 --- a/source/funkin/options/keybinds/KeybindsOptions.hx +++ b/source/funkin/options/keybinds/KeybindsOptions.hx @@ -1,9 +1,6 @@ package funkin.options.keybinds; -import funkin.backend.system.Controls; -import flixel.addons.transition.FlxTransitionableState; import flixel.util.FlxColor; -import flixel.input.keyboard.FlxKey; using StringTools; diff --git a/source/funkin/options/type/ArrayOption.hx b/source/funkin/options/type/ArrayOption.hx index edbc4e72..40c4942c 100644 --- a/source/funkin/options/type/ArrayOption.hx +++ b/source/funkin/options/type/ArrayOption.hx @@ -1,7 +1,5 @@ package funkin.options.type; -import flixel.effects.FlxFlicker; - class ArrayOption extends OptionType { public var selectCallback:String->Void; @@ -31,17 +29,12 @@ class ArrayOption extends OptionType { this.parent = parent; - if(Reflect.field(parent, optionName) != null) - { - if(options.indexOf(Reflect.field(parent, optionName)) != -1) - this.currentSelection = options.indexOf(Reflect.field(parent, optionName)); - else - this.currentSelection = 0; - } - - + var fieldValue = Reflect.field(parent, optionName); + if(fieldValue != null) + this.currentSelection = Std.int(Math.max(0, options.indexOf(fieldValue))); + this.optionName = optionName; - + add(__text = new Alphabet(100, 20, text, true)); add(__selectiontext = new Alphabet(__text.width + 120, -30, formatTextOption(), false)); } @@ -52,7 +45,7 @@ class ArrayOption extends OptionType { public override function onChangeSelection(change:Float):Void { - if(currentSelection <= 0 && change == -1 || currentSelection >= options.length - 1 && change == 1 ) return; + if(currentSelection <= 0 && change == -1 || currentSelection >= options.length - 1 && change == 1) return; currentSelection += Math.round(change); __selectiontext.text = formatTextOption(); Reflect.setField(parent, optionName, options[currentSelection]); diff --git a/source/funkin/options/type/Checkbox.hx b/source/funkin/options/type/Checkbox.hx index d0b67ff2..ba8b0519 100644 --- a/source/funkin/options/type/Checkbox.hx +++ b/source/funkin/options/type/Checkbox.hx @@ -2,7 +2,6 @@ package funkin.options.type; import flixel.math.FlxPoint; -@:allow() class Checkbox extends TextOption { public var checkbox:FlxSprite; diff --git a/source/funkin/options/type/EditorIconOption.hx b/source/funkin/options/type/EditorIconOption.hx index 9ad5928f..5303fb01 100644 --- a/source/funkin/options/type/EditorIconOption.hx +++ b/source/funkin/options/type/EditorIconOption.hx @@ -1,6 +1,5 @@ package funkin.options.type; -import funkin.game.HealthIcon; import flixel.util.FlxColor; class EditorIconOption extends IconOption { diff --git a/source/funkin/options/type/OptionType.hx b/source/funkin/options/type/OptionType.hx index 7a7d4077..c7de837d 100644 --- a/source/funkin/options/type/OptionType.hx +++ b/source/funkin/options/type/OptionType.hx @@ -2,7 +2,6 @@ package funkin.options.type; import funkin.backend.system.Controls; import flixel.group.FlxSpriteGroup; -import funkin.options.OptionsScreen; class OptionType extends FlxSpriteGroup { public var controls(get, null):Controls; diff --git a/source/lime/_internal/backend/native/NativeWindow.hx b/source/lime/_internal/backend/native/NativeWindow.hx index 76fab152..9d318ec9 100644 --- a/source/lime/_internal/backend/native/NativeWindow.hx +++ b/source/lime/_internal/backend/native/NativeWindow.hx @@ -108,7 +108,7 @@ class NativeWindow #if (!macro && lime_cffi) handle = NativeCFFI.lime_window_create(parent.application.__backend.handle, width, height, flags, title); - #if DARK_MODE_WINDOW + #if (DARK_MODE_WINDOW && !macro) funkin.backend.utils.NativeAPI.setDarkMode(title, true); #end @@ -727,7 +727,7 @@ class NativeWindow } } -@:enum private abstract MouseCursorType(Int) from Int to Int +enum abstract MouseCursorType(Int) from Int to Int { var HIDDEN = 0; var ARROW = 1; @@ -744,7 +744,7 @@ class NativeWindow var WAIT_ARROW = 12; } -@:enum private abstract WindowFlags(Int) +enum abstract WindowFlags(Int) { var WINDOW_FLAG_FULLSCREEN = 0x00000001; var WINDOW_FLAG_BORDERLESS = 0x00000002; diff --git a/source/lime/system/System.hx b/source/lime/system/System.hx index c269456f..34599615 100644 --- a/source/lime/system/System.hx +++ b/source/lime/system/System.hx @@ -533,7 +533,7 @@ class System @:noCompletion private static function __registerEntryPoint(projectName:String, entryPoint:Function):Void { // executes first!! - #if sys + #if (sys && !macro) funkin.backend.utils.NativeAPI.registerAsDPICompatible(); funkin.backend.system.CommandLineHandler.parseCommandLine(Sys.args()); #end @@ -824,7 +824,7 @@ class System } } -@:enum private abstract SystemDirectory(Int) from Int to Int from UInt to UInt +enum abstract SystemDirectory(Int) from Int to Int from UInt to UInt { var APPLICATION = 0; var APPLICATION_STORAGE = 1; diff --git a/source/lime/utils/Log.hx b/source/lime/utils/Log.hx index ebf2c764..633cc71c 100644 --- a/source/lime/utils/Log.hx +++ b/source/lime/utils/Log.hx @@ -1,7 +1,9 @@ package lime.utils; import haxe.PosInfos; +#if !macro import funkin.backend.system.Logs as FunkinLogs; +#end #if !lime_debug @:fileXml('tags="haxe,release"') @@ -30,14 +32,23 @@ class Log { var message = '[${info.className}] $message'; + #if !macro FunkinLogs.trace(message, ERROR, RED); + #else + trace(message); + #end } } public static function info(message:Dynamic, ?info:PosInfos):Void { - if (level >= LogLevel.INFO) + if (level >= LogLevel.INFO) { + #if !macro FunkinLogs.trace('[${info.className}] $message', INFO, RED); + #else + trace('[${info.className}] $message'); + #end + } } public static inline function print(message:Dynamic):Void @@ -68,15 +79,24 @@ class Log public static function verbose(message:Dynamic, ?info:PosInfos):Void { - if (level >= LogLevel.VERBOSE) + if (level >= LogLevel.VERBOSE) { + #if !macro FunkinLogs.trace('[${info.className}] $message', VERBOSE); + #else + trace('[${info.className}] $message'); + #end + } } public static function warn(message:Dynamic, ?info:PosInfos):Void { if (level >= LogLevel.WARN) { + #if !macro FunkinLogs.trace('[${info.className}] $message', WARNING, YELLOW); + #else + trace('[${info.className}] $message'); + #end } } diff --git a/source/openfl/display3D/Context3D.hx b/source/openfl/display3D/Context3D.hx index 97f9118b..8443824d 100644 --- a/source/openfl/display3D/Context3D.hx +++ b/source/openfl/display3D/Context3D.hx @@ -27,6 +27,7 @@ import openfl.utils._internal.UInt8Array; import openfl.utils.AGALMiniAssembler; import openfl.utils.ByteArray; #if lime +import lime.graphics.opengl.GL; import lime.graphics.Image; import lime.graphics.ImageBuffer; import lime.graphics.RenderContext; @@ -271,7 +272,7 @@ import lime.math.Vector2; @:noCompletion private var __enableErrorChecking:Bool; @:noCompletion private var __fragmentConstants:Float32Array; @:noCompletion private var __frontBufferTexture:RectangleTexture; - @:noCompletion private var __positionScale:Float32Array; + @:noCompletion private var __positionScale:Float32Array; // TODO: Better approach? @:noCompletion private var __present:Bool; @:noCompletion private var __programs:Map; @:noCompletion private var __quadIndexBuffer:IndexBuffer3D; @@ -291,7 +292,11 @@ import lime.math.Vector2; __stage3D = stage3D; __context = stage.window.context; + #if (js && html5 && dom) + gl = GL.context; + #else gl = __context.webgl; + #end if (__contextState == null) __contextState = new Context3DState(); __state = new Context3DState(); @@ -575,6 +580,14 @@ import lime.math.Vector2; public function configureBackBuffer(width:Int, height:Int, antiAlias:Int, enableDepthAndStencil:Bool = true, wantsBestResolution:Bool = false, wantsBestResolutionOnBrowserZoom:Bool = false):Void { + #if !openfl_dpi_aware + if (wantsBestResolution) + { + width = Std.int(width * __stage.window.scale); + height = Std.int(height * __stage.window.scale); + } + #end + if (__stage3D == null) { backBufferWidth = width; @@ -600,7 +613,16 @@ import lime.math.Vector2; __stage3D.__vertexBuffer = createVertexBuffer(4, 5); } - var vertexData = new Vector([width, height, 0, 1, 1, 0, height, 0, 0, 1, width, 0, 0, 1, 0, 0, 0, 0, 0, 0.0]); + #if openfl_dpi_aware + var scaledWidth = width; + var scaledHeight = height; + #else + var scaledWidth = wantsBestResolution ? width : Std.int(width * __stage.window.scale); + var scaledHeight = wantsBestResolution ? height : Std.int(height * __stage.window.scale); + #end + var vertexData = new Vector([ + scaledWidth, scaledHeight, 0, 1, 1, 0, scaledHeight, 0, 0, 1, scaledWidth, 0, 0, 1, 0, 0, 0, 0, 0, 0.0 + ]); __stage3D.__vertexBuffer.uploadFromVector(vertexData, 0, 20); @@ -1000,6 +1022,8 @@ import lime.math.Vector2; **/ public function dispose(recreate:Bool = true):Void { + // TODO: Dispose all related buffers + gl = null; __dispose(); } @@ -1172,12 +1196,14 @@ import lime.math.Vector2; #if !openfl_disable_display_render if (__state.renderToTexture == null) { + // TODO: Make sure state is correct for this? if (__stage.context3D == this && !__stage.__renderer.__cleared) { __stage.__renderer.__clear(); } else if (!__cleared) { + // TODO: Throw error if error reporting is enabled? clear(0, 0, 0, 0, 1, 0, Context3DClearMask.COLOR); } } @@ -1223,7 +1249,7 @@ import lime.math.Vector2; if (!__cleared) { // Make sure texture is initialized - // BASE-TODO: Throw error if error reporting is enabled? + // TODO: Throw error if error reporting is enabled? clear(0, 0, 0, 0, 1, 0, Context3DClearMask.COLOR); } @@ -1284,7 +1310,7 @@ import lime.math.Vector2; __state.blendSourceAlphaFactor = sourceAlphaFactor; __state.blendDestinationAlphaFactor = destinationAlphaFactor; - // BASE-TODO: Better way to handle this? + // TODO: Better way to handle this? __setGLBlendEquation(gl.FUNC_ADD); } @@ -1363,7 +1389,7 @@ import lime.math.Vector2; public function setProgram(program:Program3D):Void { __state.program = program; - __state.shader = null; // BASE-TODO: Merge this logic + __state.shader = null; // TODO: Merge this logic if (program != null) { @@ -1407,11 +1433,11 @@ import lime.math.Vector2; if (__state.program != null && __state.program.__format == GLSL) { - // BASE-TODO + // TODO } else { - // BASE-TODO: Cleanup? + // TODO: Cleanup? if (numRegisters == -1) { @@ -1421,7 +1447,7 @@ import lime.math.Vector2; var isVertex = (programType == VERTEX); var dest = isVertex ? __vertexConstants : __fragmentConstants; - var floatData = Float32Array.fromBytes(data, 0, data.length); + var floatData = Float32Array.fromBytes(data, 0); var outOffset = firstRegister * 4; var inOffset = Std.int(byteArrayOffset / 4); @@ -1465,7 +1491,7 @@ import lime.math.Vector2; { __flushGLProgram(); - // BASE-TODO: Cache value, prevent need to copy + // TODO: Cache value, prevent need to copy var data = new Float32Array(16); for (i in 0...16) { @@ -1867,6 +1893,8 @@ import lime.math.Vector2; **/ public function setVertexBufferAt(index:Int, buffer:VertexBuffer3D, bufferOffset:Int = 0, format:Context3DVertexBufferFormat = FLOAT_4):Void { + if (index < 0) return; + if (buffer == null) { gl.disableVertexAttribArray(index); @@ -1930,7 +1958,7 @@ import lime.math.Vector2; @:noCompletion private function __bindGLTexture2D(texture:GLTexture):Void { - // BASE-TODO: Need to consider activeTexture ID + // TODO: Need to consider activeTexture ID // if (#if openfl_disable_context_cache true #else __contextState.__currentGLTexture2D != texture #end) { @@ -1942,7 +1970,7 @@ import lime.math.Vector2; @:noCompletion private function __bindGLTextureCubeMap(texture:GLTexture):Void { - // BASE-TODO: Need to consider activeTexture ID + // TODO: Need to consider activeTexture ID // if (#if openfl_disable_context_cache true #else __contextState.__currentGLTextureCubeMap != texture #end) { @@ -1981,14 +2009,14 @@ import lime.math.Vector2; #if !openfl_disable_display_render if (__state.renderToTexture == null) { - // BASE-TODO: Make sure state is correct for this? + // TODO: Make sure state is correct for this? if (__stage.context3D == this && !__stage.__renderer.__cleared) { __stage.__renderer.__clear(); } else if (!__cleared) { - // BASE-TODO: Throw error if error reporting is enabled? + // TODO: Throw error if error reporting is enabled? clear(0, 0, 0, 0, 1, 0, Context3DClearMask.COLOR); } } @@ -2184,7 +2212,7 @@ import lime.math.Vector2; if (#if openfl_disable_context_cache true #else __contextState.shader != shader #end) { - // BASE-TODO: Merge this logic + // TODO: Merge this logic if (__contextState.shader != null) { @@ -2240,11 +2268,20 @@ import lime.math.Vector2; var scissorY = Std.int(__state.scissorRectangle.y); var scissorWidth = Std.int(__state.scissorRectangle.width); var scissorHeight = Std.int(__state.scissorRectangle.height); + #if !openfl_dpi_aware + if (__backBufferWantsBestResolution) + { + scissorX = Std.int(__state.scissorRectangle.x * __stage.window.scale); + scissorY = Std.int(__state.scissorRectangle.y * __stage.window.scale); + scissorWidth = Std.int(__state.scissorRectangle.width * __stage.window.scale); + scissorHeight = Std.int(__state.scissorRectangle.height * __stage.window.scale); + } + #end if (__state.renderToTexture == null && __stage3D == null) { var contextHeight = Std.int(__stage.window.height * __stage.window.scale); - scissorY = contextHeight - Std.int(__state.scissorRectangle.height) - scissorY; + scissorY = contextHeight - scissorHeight - scissorY; } if (#if openfl_disable_context_cache true #else __contextState.scissorRectangle.x != scissorX @@ -2312,7 +2349,7 @@ import lime.math.Vector2; { // if (#if openfl_disable_context_cache true #else texture != __contextState.textures[i] #end) { - // BASE-TODO: Cleaner approach? + // TODO: Cleaner approach? if (texture.__textureTarget == gl.TEXTURE_2D) { __bindGLTexture2D(texture.__getTexture()); @@ -2323,7 +2360,7 @@ import lime.math.Vector2; } #if (desktop && !html5) - // BASE-TODO: Cache? + // TODO: Cache? gl.enable(gl.TEXTURE_2D); #end @@ -2357,7 +2394,7 @@ import lime.math.Vector2; gl.uniform1i(__state.program.__agalAlphaSamplerEnabled[sampler].location, 1); #if (desktop && !html5) - // BASE-TODO: Cache? + // TODO: Cache? gl.enable(gl.TEXTURE_2D); #end } @@ -2377,15 +2414,24 @@ import lime.math.Vector2; @:noCompletion private function __flushGLViewport():Void { - // BASE-TODO: Cache + // TODO: Cache if (__state.renderToTexture == null) { if (__stage.context3D == this) { + var scaledBackBufferWidth = backBufferWidth; + var scaledBackBufferHeight = backBufferHeight; + #if !openfl_dpi_aware + if (__stage3D == null && !__backBufferWantsBestResolution) + { + scaledBackBufferWidth = Std.int(backBufferWidth * __stage.window.scale); + scaledBackBufferHeight = Std.int(backBufferHeight * __stage.window.scale); + } + #end var x = __stage3D == null ? 0 : Std.int(__stage3D.x); - var y = Std.int((__stage.window.height * __stage.window.scale) - backBufferHeight - (__stage3D == null ? 0 : __stage3D.y)); - gl.viewport(x, y, backBufferWidth, backBufferHeight); + var y = Std.int((__stage.window.height * __stage.window.scale) - scaledBackBufferHeight - (__stage3D == null ? 0 : __stage3D.y)); + gl.viewport(x, y, scaledBackBufferWidth, scaledBackBufferHeight); } else { @@ -2396,7 +2442,7 @@ import lime.math.Vector2; { var width = 0, height = 0; - // BASE-TODO: Avoid use of Std.is + // TODO: Avoid use of Std.is if ((__state.renderToTexture is Texture)) { var texture2D:Texture = cast __state.renderToTexture; @@ -2460,7 +2506,7 @@ import lime.math.Vector2; case GREATER: gl.GREATER; case GREATER_EQUAL: gl.GEQUAL; case LESS: gl.LESS; - case LESS_EQUAL: gl.LEQUAL; // BASE-TODO : wrong value + case LESS_EQUAL: gl.LEQUAL; // TODO : wrong value case NEVER: gl.NEVER; case NOT_EQUAL: gl.NOTEQUAL; default: gl.EQUAL; @@ -2655,7 +2701,7 @@ import lime.math.Vector2; { if (__glMemoryCurrentAvailable != -1) { - // BASE-TODO: Return amount used by this application only + // TODO: Return amount used by this application only var current = gl.getParameter(__glMemoryCurrentAvailable); var total = gl.getParameter(__glMemoryTotalAvailable); diff --git a/source/openfl/media/Sound.hx b/source/openfl/media/Sound.hx index 32a471ff..b0632e78 100644 --- a/source/openfl/media/Sound.hx +++ b/source/openfl/media/Sound.hx @@ -636,10 +636,12 @@ class Sound extends EventDispatcher return null; } + #if !macro if (changeID < funkin.backend.system.Main.changeID) { changeID = funkin.backend.system.Main.changeID; regen(); } + #end if (sndTransform == null) { diff --git a/source/openfl/utils/Assets.hx b/source/openfl/utils/Assets.hx index 528632ca..e08852cd 100644 --- a/source/openfl/utils/Assets.hx +++ b/source/openfl/utils/Assets.hx @@ -1,8 +1,10 @@ package openfl.utils; +#if !macro import funkin.backend.system.Main; import funkin.options.Options; import funkin.backend.system.OptimizedBitmapData; +#end import openfl.utils._internal.Log; import openfl.display.BitmapData; import openfl.display.MovieClip; @@ -113,10 +115,10 @@ class Assets var bitmapData = image.src; #else var bitmapData:BitmapData = null; - if (pushToGPU && !Main.forceGPUOnlyBitmapsOff && Options.gpuOnlyBitmaps) { + #if !macro if (pushToGPU && !Main.forceGPUOnlyBitmapsOff && Options.gpuOnlyBitmaps) { bitmapData = new OptimizedBitmapData(0, 0, true, 0); bitmapData.__fromImage(image); - } else { + } else #end { bitmapData = BitmapData.fromImage(image); } #end @@ -497,10 +499,10 @@ class Assets var bitmapData = image.src; #else var bitmapData:BitmapData = null; - if (!Main.forceGPUOnlyBitmapsOff && Options.gpuOnlyBitmaps) { + #if !macro if (!Main.forceGPUOnlyBitmapsOff && Options.gpuOnlyBitmaps) { bitmapData = new OptimizedBitmapData(0, 0, true, 0); bitmapData.__fromImage(image); - } else { + } else #end { bitmapData = BitmapData.fromImage(image); } #end