mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2025-04-22 03:34:10 -04:00
Note quant snapping
This commit is contained in:
parent
234dc0ac19
commit
a2d803cc83
10 changed files with 633 additions and 147 deletions
hmm.json
source/funkin
29
hmm.json
29
hmm.json
|
@ -11,14 +11,14 @@
|
|||
"name": "flixel",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "8ff2aa9",
|
||||
"ref": "a629f9a5",
|
||||
"url": "https://github.com/MasterEric/flixel"
|
||||
},
|
||||
{
|
||||
"name": "flixel-addons",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "157eaf3",
|
||||
"ref": "752c3d7",
|
||||
"url": "https://github.com/MasterEric/flixel-addons"
|
||||
},
|
||||
{
|
||||
|
@ -30,26 +30,26 @@
|
|||
"name": "flxanimate",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "58d5d27",
|
||||
"ref": "18b2060",
|
||||
"url": "https://github.com/Dot-Stuff/flxanimate"
|
||||
},
|
||||
{
|
||||
"name": "format",
|
||||
"type": "haxelib",
|
||||
"version": null
|
||||
"version": "3.5.0"
|
||||
},
|
||||
{
|
||||
"name": "haxeui-core",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "3f229bd",
|
||||
"ref": "fc8d656b",
|
||||
"url": "https://github.com/haxeui/haxeui-core/"
|
||||
},
|
||||
{
|
||||
"name": "haxeui-flixel",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "be1f404",
|
||||
"ref": "80941a7",
|
||||
"url": "https://github.com/haxeui/haxeui-flixel"
|
||||
},
|
||||
{
|
||||
|
@ -57,11 +57,6 @@
|
|||
"type": "haxelib",
|
||||
"version": "2.1.0"
|
||||
},
|
||||
{
|
||||
"name": "haxe-concurrent",
|
||||
"type": "haxelib",
|
||||
"version": "3.0.2"
|
||||
},
|
||||
{
|
||||
"name": "hscript",
|
||||
"type": "haxelib",
|
||||
|
@ -84,23 +79,21 @@
|
|||
},
|
||||
{
|
||||
"name": "lime",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "4c82152",
|
||||
"url": "https://github.com/openfl/lime"
|
||||
"type": "haxelib",
|
||||
"version": null
|
||||
},
|
||||
{
|
||||
"name": "openfl",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "3fd5763",
|
||||
"url": "https://github.com/MasterEric/openfl/"
|
||||
"ref": "3fd5763c1",
|
||||
"url": "https://github.com/MasterEric/openfl"
|
||||
},
|
||||
{
|
||||
"name": "polymod",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "develop",
|
||||
"ref": "547c8ee",
|
||||
"url": "https://github.com/larsiusprime/polymod"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -63,13 +63,33 @@ class Conductor
|
|||
}
|
||||
|
||||
/**
|
||||
* Duration of a step in milliseconds. Calculated based on bpm.
|
||||
* Duration of a step (quarter) in milliseconds. Calculated based on bpm.
|
||||
*/
|
||||
public static var stepCrochet(get, null):Float;
|
||||
|
||||
static function get_stepCrochet():Float
|
||||
{
|
||||
return crochet / 4;
|
||||
return crochet / timeSignatureNumerator;
|
||||
}
|
||||
|
||||
public static var timeSignatureNumerator(get, null):Int;
|
||||
|
||||
static function get_timeSignatureNumerator():Int
|
||||
{
|
||||
if (currentTimeChange == null)
|
||||
return 4;
|
||||
|
||||
return currentTimeChange.timeSignatureNum;
|
||||
}
|
||||
|
||||
public static var timeSignatureDenominator(get, null):Int;
|
||||
|
||||
static function get_timeSignatureDenominator():Int
|
||||
{
|
||||
if (currentTimeChange == null)
|
||||
return 4;
|
||||
|
||||
return currentTimeChange.timeSignatureDen;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -124,10 +144,12 @@ class Conductor
|
|||
* Forcibly defines the current BPM of the song.
|
||||
* Useful for things like the chart editor that need to manipulate BPM in real time.
|
||||
*
|
||||
* Set to null to reset to the BPM defined by the timeChanges.
|
||||
*
|
||||
* WARNING: Avoid this for things like setting the BPM of the title screen music,
|
||||
* you should have a metadata file for it instead.
|
||||
*/
|
||||
public static function forceBPM(bpm:Float)
|
||||
public static function forceBPM(?bpm:Float = null)
|
||||
{
|
||||
trace('[CONDUCTOR] Forcing BPM to ' + bpm);
|
||||
Conductor.bpmOverride = bpm;
|
||||
|
|
|
@ -77,6 +77,7 @@ class MusicBeatState extends FlxUIState
|
|||
}
|
||||
|
||||
FlxG.watch.addQuick("songPos", Conductor.songPosition);
|
||||
FlxG.watch.addQuick("bpm", Conductor.bpm);
|
||||
|
||||
dispatchEvent(new UpdateScriptEvent(elapsed));
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ class FlxAudioGroup extends FlxTypedGroup<FlxSound>
|
|||
var result:FlxSound = super.add(sound);
|
||||
|
||||
if (result == null)
|
||||
return;
|
||||
return null;
|
||||
|
||||
// Apply parameters to the new sound.
|
||||
result.autoDestroy = this.autoDestroyMembers;
|
||||
|
@ -126,6 +126,8 @@ class FlxAudioGroup extends FlxTypedGroup<FlxSound>
|
|||
result.play(true, 0.0);
|
||||
result.pause();
|
||||
result.time = this.time;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,10 +25,12 @@ class PolymodHandler
|
|||
|
||||
public static function createModRoot()
|
||||
{
|
||||
#if sys
|
||||
if (!sys.FileSystem.exists(MOD_FOLDER))
|
||||
{
|
||||
sys.FileSystem.createDirectory(MOD_FOLDER);
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -196,11 +196,11 @@ class HealthIcon extends FlxSprite
|
|||
// Make the health icons bump (the update function causes them to lerp back down).
|
||||
if (this.width > this.height)
|
||||
{
|
||||
setGraphicSize(this.width + (HEALTH_ICON_SIZE * this.size.x * 0.2), 0);
|
||||
setGraphicSize(Std.int(this.width + (HEALTH_ICON_SIZE * this.size.x * 0.2)), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
setGraphicSize(0, this.height + (HEALTH_ICON_SIZE * this.size.y * 0.2));
|
||||
setGraphicSize(0, Std.int(this.height + (HEALTH_ICON_SIZE * this.size.y * 0.2)));
|
||||
}
|
||||
this.updateHitbox();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package funkin.ui.debug.charting;
|
||||
|
||||
import flixel.FlxObject;
|
||||
import flixel.FlxBasic;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.graphics.frames.FlxFramesCollection;
|
||||
import flixel.graphics.frames.FlxTileFrames;
|
||||
|
@ -12,17 +14,14 @@ import funkin.play.song.SongData.SongNoteData;
|
|||
*/
|
||||
class ChartEditorNoteSprite extends FlxSprite
|
||||
{
|
||||
public var parentState:ChartEditorState;
|
||||
|
||||
/**
|
||||
* The note data that this sprite represents.
|
||||
* You can set this to null to kill the sprite and flag it for recycling.
|
||||
*/
|
||||
public var noteData(default, set):SongNoteData;
|
||||
|
||||
/**
|
||||
* The note skin that this sprite displays.
|
||||
*/
|
||||
public var noteSkin(default, set):String = 'Normal';
|
||||
|
||||
/**
|
||||
* This note is the previous sprite in a sustain chain.
|
||||
*/
|
||||
|
@ -33,10 +32,12 @@ class ChartEditorNoteSprite extends FlxSprite
|
|||
*/
|
||||
public var childNoteSprite(default, set):ChartEditorNoteSprite = null;
|
||||
|
||||
public function new()
|
||||
public function new(parent:ChartEditorState)
|
||||
{
|
||||
super();
|
||||
|
||||
this.parentState = parent;
|
||||
|
||||
if (noteFrameCollection == null)
|
||||
{
|
||||
initFrameCollection();
|
||||
|
@ -131,26 +132,12 @@ class ChartEditorNoteSprite extends FlxSprite
|
|||
playNoteAnimation();
|
||||
|
||||
// Update the position to match the note data.
|
||||
setNotePosition();
|
||||
updateNotePosition();
|
||||
|
||||
return this.noteData;
|
||||
}
|
||||
|
||||
function set_noteSkin(value:String):String
|
||||
{
|
||||
// Don't update if the skin hasn't changed.
|
||||
if (value == this.noteSkin)
|
||||
return this.noteSkin;
|
||||
|
||||
this.noteSkin = value;
|
||||
|
||||
// Make sure to update the graphic to match the note skin.
|
||||
playNoteAnimation();
|
||||
|
||||
return this.noteSkin;
|
||||
}
|
||||
|
||||
function setNotePosition()
|
||||
public function updateNotePosition(?origin:FlxObject)
|
||||
{
|
||||
var cursorColumn:Int = this.noteData.data;
|
||||
|
||||
|
@ -179,7 +166,13 @@ class ChartEditorNoteSprite extends FlxSprite
|
|||
|
||||
// Notes far in the song will start far down, but the group they belong to will have a high negative offset.
|
||||
// TODO: stepTime doesn't account for fluctuating BPMs.
|
||||
this.y = this.noteData.stepTime * ChartEditorState.GRID_SIZE;
|
||||
if (this.noteData.stepTime >= 0)
|
||||
this.y = this.noteData.stepTime * ChartEditorState.GRID_SIZE;
|
||||
|
||||
if (origin != null) {
|
||||
this.x += origin.x;
|
||||
this.y += origin.y;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -214,7 +207,6 @@ class ChartEditorNoteSprite extends FlxSprite
|
|||
if (this.parentNoteSprite != null)
|
||||
{
|
||||
this.noteData = this.parentNoteSprite.noteData;
|
||||
this.noteSkin = this.parentNoteSprite.noteSkin;
|
||||
}
|
||||
|
||||
return this.parentNoteSprite;
|
||||
|
@ -227,13 +219,12 @@ class ChartEditorNoteSprite extends FlxSprite
|
|||
if (this.parentNoteSprite != null)
|
||||
{
|
||||
this.noteData = this.parentNoteSprite.noteData;
|
||||
this.noteSkin = this.parentNoteSprite.noteSkin;
|
||||
}
|
||||
|
||||
return this.childNoteSprite;
|
||||
}
|
||||
|
||||
function playNoteAnimation()
|
||||
public function playNoteAnimation()
|
||||
{
|
||||
// Decide whether to display a note or a sustain.
|
||||
var baseAnimationName:String = 'tap';
|
||||
|
@ -241,7 +232,7 @@ class ChartEditorNoteSprite extends FlxSprite
|
|||
baseAnimationName = (this.childNoteSprite != null) ? 'hold' : 'holdEnd';
|
||||
|
||||
// Play the appropriate animation for the type, direction, and skin.
|
||||
var animationName = '${baseAnimationName}${this.noteData.getDirectionName()}${this.noteSkin}';
|
||||
var animationName = '${baseAnimationName}${this.noteData.getDirectionName()}${this.parentState.currentSongNoteSkin}';
|
||||
|
||||
this.animation.play(animationName);
|
||||
|
||||
|
@ -266,7 +257,7 @@ class ChartEditorNoteSprite extends FlxSprite
|
|||
this.updateHitbox();
|
||||
|
||||
// TODO: Make this an attribute of the note skin.
|
||||
this.antialiasing = (noteSkin != 'Pixel');
|
||||
this.antialiasing = (this.parentState.currentSongNoteSkin != 'Pixel');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -117,16 +117,31 @@ class ChartEditorState extends HaxeUIState
|
|||
*/
|
||||
static final DRAG_THRESHOLD:Float = 16.0;
|
||||
|
||||
/**
|
||||
* Types of notes you can snap to.
|
||||
*/
|
||||
static final SNAP_QUANTS:Array<Int> = [4, 8, 12, 16, 20, 24, 32, 48, 64, 96, 192];
|
||||
|
||||
/**
|
||||
* INSTANCE DATA
|
||||
*/
|
||||
// ==============================
|
||||
public var currentZoomLevel:Float = 1.0;
|
||||
|
||||
var noteSnapQuantIndex:Int = 3;
|
||||
|
||||
public var noteSnapQuant(get, never):Int;
|
||||
|
||||
function get_noteSnapQuant():Int
|
||||
{
|
||||
return SNAP_QUANTS[noteSnapQuantIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* scrollPosition is the current position in the song, in pixels.
|
||||
* One pixel is 1/40 of 1 step, and 1/160 of 1 beat.
|
||||
*/
|
||||
var scrollPosition(default, set):Float = -1.0;
|
||||
var scrollPositionInPixels(default, set):Float = -1.0;
|
||||
|
||||
/**
|
||||
* scrollPosition, converted to steps.
|
||||
|
@ -136,7 +151,7 @@ class ChartEditorState extends HaxeUIState
|
|||
|
||||
function get_scrollPositionInSteps():Float
|
||||
{
|
||||
return scrollPosition / GRID_SIZE;
|
||||
return scrollPositionInPixels / GRID_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -152,7 +167,7 @@ class ChartEditorState extends HaxeUIState
|
|||
|
||||
function set_scrollPositionInMs(value:Float):Float
|
||||
{
|
||||
scrollPosition = value / Conductor.stepCrochet;
|
||||
scrollPositionInPixels = value / Conductor.stepCrochet;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -162,7 +177,7 @@ class ChartEditorState extends HaxeUIState
|
|||
* 40 means the playhead is 1 grid length below the base position.
|
||||
* -40 means the playhead is 1 grid length above the base position.
|
||||
*/
|
||||
var playheadPosition(default, set):Float;
|
||||
var playheadPositionInPixels(default, set):Float;
|
||||
|
||||
var playheadPositionInSteps(get, null):Float;
|
||||
|
||||
|
@ -171,7 +186,7 @@ class ChartEditorState extends HaxeUIState
|
|||
*/
|
||||
function get_playheadPositionInSteps():Float
|
||||
{
|
||||
return playheadPosition / GRID_SIZE;
|
||||
return playheadPositionInPixels / GRID_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -187,14 +202,14 @@ class ChartEditorState extends HaxeUIState
|
|||
/**
|
||||
* This is the song's length in PIXELS, same format as scrollPosition.
|
||||
*/
|
||||
var songLength(get, default):Int;
|
||||
var songLengthInPixels(get, default):Int;
|
||||
|
||||
function get_songLength():Int
|
||||
function get_songLengthInPixels():Int
|
||||
{
|
||||
if (songLength <= 0)
|
||||
if (songLengthInPixels <= 0)
|
||||
return 1000;
|
||||
|
||||
return songLength;
|
||||
return songLengthInPixels;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -204,7 +219,7 @@ class ChartEditorState extends HaxeUIState
|
|||
|
||||
function get_songLengthInSteps():Float
|
||||
{
|
||||
return songLength / GRID_SIZE;
|
||||
return songLengthInPixels / GRID_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -273,7 +288,7 @@ class ChartEditorState extends HaxeUIState
|
|||
// Make sure view is updated when we change view modes.
|
||||
noteDisplayDirty = true;
|
||||
notePreviewDirty = true;
|
||||
this.scrollPosition = this.scrollPosition;
|
||||
this.scrollPositionInPixels = this.scrollPositionInPixels;
|
||||
|
||||
return isViewDownscroll;
|
||||
}
|
||||
|
@ -367,7 +382,7 @@ class ChartEditorState extends HaxeUIState
|
|||
// Make sure view is updated when we change modes.
|
||||
noteDisplayDirty = true;
|
||||
notePreviewDirty = true;
|
||||
this.scrollPosition = 0;
|
||||
this.scrollPositionInPixels = 0;
|
||||
|
||||
return isInPatternMode;
|
||||
}
|
||||
|
@ -595,7 +610,7 @@ class ChartEditorState extends HaxeUIState
|
|||
return value;
|
||||
}
|
||||
|
||||
var currentSongNoteSkin(get, set):String;
|
||||
public var currentSongNoteSkin(get, set):String;
|
||||
|
||||
function get_currentSongNoteSkin():String
|
||||
{
|
||||
|
@ -696,9 +711,9 @@ class ChartEditorState extends HaxeUIState
|
|||
var gridPlayheadScrollArea:FlxSprite;
|
||||
|
||||
/**
|
||||
* A sprite used to highlight the grid square under the cursor.
|
||||
* A sprite used to indicate the note that will be placed on click.
|
||||
*/
|
||||
var gridCursor:FlxSprite;
|
||||
var gridGhostNote:ChartEditorNoteSprite;
|
||||
|
||||
/**
|
||||
* The waveform which (optionally) displays over the grid, underneath the notes and playhead.
|
||||
|
@ -823,14 +838,11 @@ class ChartEditorState extends HaxeUIState
|
|||
gridTiledSprite.y = MENU_BAR_HEIGHT + GRID_TOP_PAD; // Push down to account for the menu bar.
|
||||
add(gridTiledSprite);
|
||||
|
||||
/*
|
||||
buildSpectrogram(audioVocalTrack);
|
||||
*/
|
||||
|
||||
// The cursor that appears when hovering over the grid.
|
||||
var gridCursorSize:Int = Std.int(GRID_SIZE - GRID_SELECTION_BORDER_WIDTH);
|
||||
gridCursor = new FlxSprite().makeGraphic(gridCursorSize, gridCursorSize, CURSOR_COLOR);
|
||||
add(gridCursor);
|
||||
gridGhostNote = new ChartEditorNoteSprite(this);
|
||||
gridGhostNote.alpha = 0.8;
|
||||
gridGhostNote.noteData = new SongNoteData(-1, -1, 0, "");
|
||||
gridGhostNote.visible = false;
|
||||
add(gridGhostNote);
|
||||
|
||||
buildNoteGroup();
|
||||
|
||||
|
@ -975,7 +987,7 @@ class ChartEditorState extends HaxeUIState
|
|||
playbarHeadDragging = false;
|
||||
|
||||
// Set the song position to where the playhead was moved to.
|
||||
scrollPosition = songLength * (playbarHead.value / 100);
|
||||
scrollPositionInPixels = songLengthInPixels * (playbarHead.value / 100);
|
||||
// Update the conductor and audio tracks to match.
|
||||
moveSongToScrollPosition();
|
||||
|
||||
|
@ -1088,13 +1100,13 @@ class ChartEditorState extends HaxeUIState
|
|||
hitsoundsEnabledPlayer = event.value;
|
||||
});
|
||||
setUISelected('menubarItemPlayerHitsounds', hitsoundsEnabledPlayer);
|
||||
|
||||
|
||||
addUIChangeListener('menubarItemOpponentHitsounds', (event:UIEvent) ->
|
||||
{
|
||||
hitsoundsEnabledOpponent = event.value;
|
||||
});
|
||||
setUISelected('menubarItemOpponentHitsounds', hitsoundsEnabledOpponent);
|
||||
|
||||
|
||||
var instVolumeLabel:Label = findComponent('menubarLabelVolumeInstrumental', Label);
|
||||
addUIChangeListener('menubarItemVolumeInstrumental', (event:UIEvent) ->
|
||||
{
|
||||
|
@ -1210,6 +1222,8 @@ class ChartEditorState extends HaxeUIState
|
|||
|
||||
// These ones only happen if the modal dialog is not open.
|
||||
handleScrollKeybinds();
|
||||
handleZoom();
|
||||
handleSnap();
|
||||
handleCursor();
|
||||
|
||||
handleMenubar();
|
||||
|
@ -1326,7 +1340,7 @@ class ChartEditorState extends HaxeUIState
|
|||
}
|
||||
|
||||
// Mouse Wheel = Scroll
|
||||
if (FlxG.mouse.wheel != 0)
|
||||
if (FlxG.mouse.wheel != 0 && !FlxG.keys.pressed.CONTROL)
|
||||
{
|
||||
scrollAmount = -10 * FlxG.mouse.wheel;
|
||||
}
|
||||
|
@ -1365,37 +1379,73 @@ class ChartEditorState extends HaxeUIState
|
|||
if (FlxG.keys.justPressed.HOME)
|
||||
{
|
||||
// Scroll amount is the difference between the current position and the top.
|
||||
scrollAmount = 0 - this.scrollPosition;
|
||||
playheadAmount = 0 - this.playheadPosition;
|
||||
scrollAmount = 0 - this.scrollPositionInPixels;
|
||||
playheadAmount = 0 - this.playheadPositionInPixels;
|
||||
}
|
||||
if (playbarButtonPressed == 'playbarStart')
|
||||
{
|
||||
playbarButtonPressed = '';
|
||||
scrollAmount = 0 - this.scrollPosition;
|
||||
playheadAmount = 0 - this.playheadPosition;
|
||||
scrollAmount = 0 - this.scrollPositionInPixels;
|
||||
playheadAmount = 0 - this.playheadPositionInPixels;
|
||||
}
|
||||
|
||||
// END = Scroll to Bottom
|
||||
if (FlxG.keys.justPressed.END)
|
||||
{
|
||||
// Scroll amount is the difference between the current position and the bottom.
|
||||
scrollAmount = this.songLength - this.scrollPosition;
|
||||
scrollAmount = this.songLengthInPixels - this.scrollPositionInPixels;
|
||||
}
|
||||
if (playbarButtonPressed == 'playbarEnd')
|
||||
{
|
||||
playbarButtonPressed = '';
|
||||
scrollAmount = this.songLength - this.scrollPosition;
|
||||
scrollAmount = this.songLengthInPixels - this.scrollPositionInPixels;
|
||||
}
|
||||
|
||||
// Apply the scroll amount.
|
||||
this.scrollPosition += scrollAmount;
|
||||
this.playheadPosition += playheadAmount;
|
||||
this.scrollPositionInPixels += scrollAmount;
|
||||
this.playheadPositionInPixels += playheadAmount;
|
||||
|
||||
// Resync the conductor and audio tracks.
|
||||
if (scrollAmount != 0 || playheadAmount != 0)
|
||||
moveSongToScrollPosition();
|
||||
}
|
||||
|
||||
function handleZoom()
|
||||
{
|
||||
if (FlxG.keys.justPressed.MINUS)
|
||||
{
|
||||
currentZoomLevel /= 2;
|
||||
|
||||
// Update the grid.
|
||||
ChartEditorThemeHandler.updateTheme(this);
|
||||
// Update the note positions.
|
||||
noteDisplayDirty = true;
|
||||
}
|
||||
|
||||
if (FlxG.keys.justPressed.PLUS)
|
||||
{
|
||||
currentZoomLevel *= 2;
|
||||
|
||||
// Update the grid.
|
||||
ChartEditorThemeHandler.updateTheme(this);
|
||||
// Update the note positions.
|
||||
noteDisplayDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
function handleSnap()
|
||||
{
|
||||
if (FlxG.keys.justPressed.LEFT)
|
||||
{
|
||||
noteSnapQuantIndex--;
|
||||
}
|
||||
|
||||
if (FlxG.keys.justPressed.RIGHT)
|
||||
{
|
||||
noteSnapQuantIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle display of the mouse cursor.
|
||||
*/
|
||||
|
@ -1403,6 +1453,7 @@ class ChartEditorState extends HaxeUIState
|
|||
{
|
||||
// Note: If a menu is open in HaxeUI, don't handle cursor behavior.
|
||||
var shouldHandleCursor = !isCursorOverHaxeUI || (selectionBoxStartPos != null);
|
||||
var eventColumn = (STRUMLINE_SIZE * 2 + 1) - 1;
|
||||
|
||||
if (shouldHandleCursor)
|
||||
{
|
||||
|
@ -1451,16 +1502,16 @@ class ChartEditorState extends HaxeUIState
|
|||
{
|
||||
// Clicked on the playhead scroll area.
|
||||
// Move the playhead to the cursor position.
|
||||
this.playheadPosition = FlxG.mouse.screenY - MENU_BAR_HEIGHT - GRID_TOP_PAD;
|
||||
this.playheadPositionInPixels = FlxG.mouse.screenY - MENU_BAR_HEIGHT - GRID_TOP_PAD;
|
||||
moveSongToScrollPosition();
|
||||
}
|
||||
|
||||
// Cursor position snapped to the grid.
|
||||
|
||||
// The song position of the cursor, in steps.
|
||||
var cursorFractionalStep:Float = cursorY / GRID_SIZE;
|
||||
var cursorStep:Int = Math.floor(cursorFractionalStep);
|
||||
var cursorMs:Float = cursorStep * Conductor.stepCrochet;
|
||||
var cursorFractionalStep:Float = cursorY / GRID_SIZE / (16 / noteSnapQuant);
|
||||
var cursorStep:Int = Std.int(Math.floor(cursorFractionalStep));
|
||||
var cursorMs:Float = cursorStep * Conductor.stepCrochet * (16 / noteSnapQuant);
|
||||
// The direction value for the column at the cursor.
|
||||
var cursorColumn:Int = Math.floor(cursorX / GRID_SIZE);
|
||||
if (cursorColumn < 0)
|
||||
|
@ -1702,7 +1753,7 @@ class ChartEditorState extends HaxeUIState
|
|||
else
|
||||
{
|
||||
// Click a blank space to place a note and select it.
|
||||
var eventColumn = (STRUMLINE_SIZE * 2 + 1) - 1;
|
||||
|
||||
if (cursorColumn == eventColumn)
|
||||
{
|
||||
// Create an event and place it in the chart.
|
||||
|
@ -1750,28 +1801,44 @@ class ChartEditorState extends HaxeUIState
|
|||
performCommand(new RemoveNotesCommand([highlightedNote.noteData]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle grid cursor.
|
||||
if (overlapsGrid && !overlapsSelectionBorder && !gridPlayheadScrollAreaPressed)
|
||||
{
|
||||
gridCursor.visible = true;
|
||||
// X and Y are the cursor position relative to the grid, snapped to the top left of the grid square.
|
||||
gridCursor.x = Math.floor(cursorX / GRID_SIZE) * GRID_SIZE + gridTiledSprite.x + (GRID_SELECTION_BORDER_WIDTH / 2);
|
||||
gridCursor.y = cursorStep * GRID_SIZE + gridTiledSprite.y + (GRID_SELECTION_BORDER_WIDTH / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
gridCursor.visible = false;
|
||||
gridCursor.x = -9999;
|
||||
gridCursor.y = -9999;
|
||||
// Handle grid cursor.
|
||||
if (overlapsGrid && !overlapsSelectionBorder && !gridPlayheadScrollAreaPressed)
|
||||
{
|
||||
Cursor.cursorMode = Pointer;
|
||||
|
||||
// Indicate that we can pla
|
||||
gridGhostNote.visible = (cursorColumn != eventColumn);
|
||||
|
||||
if (cursorColumn != gridGhostNote.noteData.data || selectedNoteKind != gridGhostNote.noteData.kind) {
|
||||
gridGhostNote.noteData.kind = selectedNoteKind;
|
||||
gridGhostNote.noteData.data = cursorColumn;
|
||||
gridGhostNote.playNoteAnimation();
|
||||
}
|
||||
|
||||
FlxG.watch.addQuick("cursorY", cursorY);
|
||||
FlxG.watch.addQuick("cursorFractionalStep", cursorFractionalStep);
|
||||
FlxG.watch.addQuick("cursorStep", cursorStep);
|
||||
FlxG.watch.addQuick("cursorMs", cursorMs);
|
||||
|
||||
gridGhostNote.noteData.time = cursorMs;
|
||||
gridGhostNote.updateNotePosition(renderedNotes);
|
||||
|
||||
// gridCursor.visible = true;
|
||||
// // X and Y are the cursor position relative to the grid, snapped to the top left of the grid square.
|
||||
// gridCursor.x = Math.floor(cursorX / GRID_SIZE) * GRID_SIZE + gridTiledSprite.x + (GRID_SELECTION_BORDER_WIDTH / 2);
|
||||
// gridCursor.y = cursorStep * GRID_SIZE + gridTiledSprite.y + (GRID_SELECTION_BORDER_WIDTH / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
gridGhostNote.visible = false;
|
||||
Cursor.cursorMode = Default;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gridCursor.visible = false;
|
||||
gridCursor.x = -9999;
|
||||
gridCursor.y = -9999;
|
||||
gridGhostNote.visible = false;
|
||||
}
|
||||
|
||||
if (isCursorOverHaxeUIButton && Cursor.cursorMode == Default)
|
||||
|
@ -1793,9 +1860,9 @@ class ChartEditorState extends HaxeUIState
|
|||
renderedNotes.flipX = (isViewDownscroll);
|
||||
|
||||
// Calculate the view bounds.
|
||||
var viewAreaTop:Float = this.scrollPosition - GRID_TOP_PAD;
|
||||
var viewAreaTop:Float = this.scrollPositionInPixels - GRID_TOP_PAD;
|
||||
var viewHeight:Float = (FlxG.height - MENU_BAR_HEIGHT);
|
||||
var viewAreaBottom:Float = this.scrollPosition + viewHeight;
|
||||
var viewAreaBottom:Float = this.scrollPositionInPixels + viewHeight;
|
||||
|
||||
// Remove notes that are no longer visible and list the ones that are.
|
||||
var displayedNoteData:Array<SongNoteData> = [];
|
||||
|
@ -1830,7 +1897,11 @@ class ChartEditorState extends HaxeUIState
|
|||
}
|
||||
else
|
||||
{
|
||||
// Note is already displayed and should remain displayed.
|
||||
displayedNoteData.push(noteSprite.noteData);
|
||||
|
||||
// Update the note sprite's position.
|
||||
noteSprite.updateNotePosition(renderedNotes);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1839,8 +1910,11 @@ class ChartEditorState extends HaxeUIState
|
|||
{
|
||||
// Remember if we are already displaying this note.
|
||||
if (displayedNoteData.indexOf(noteData) != -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the position the note should be at.
|
||||
var noteTimePixels:Float = noteData.time / Conductor.stepCrochet * GRID_SIZE;
|
||||
|
||||
// Make sure the note appears when scrolling up.
|
||||
|
@ -1854,11 +1928,11 @@ class ChartEditorState extends HaxeUIState
|
|||
// Get a note sprite from the pool.
|
||||
// If we can reuse a deleted note, do so.
|
||||
// If a new note is needed, call buildNoteSprite.
|
||||
var noteSprite:ChartEditorNoteSprite = renderedNotes.recycle(ChartEditorNoteSprite);
|
||||
var noteSprite:ChartEditorNoteSprite = renderedNotes.recycle(() -> new ChartEditorNoteSprite(this));
|
||||
noteSprite.parentState = this;
|
||||
|
||||
// The note sprite handles animation playback and positioning.
|
||||
noteSprite.noteData = noteData;
|
||||
noteSprite.noteSkin = currentSongNoteSkin;
|
||||
|
||||
// Setting note data resets position relative to the grid so we fix that.
|
||||
noteSprite.x += renderedNotes.x;
|
||||
|
@ -1880,6 +1954,7 @@ class ChartEditorState extends HaxeUIState
|
|||
}
|
||||
|
||||
var nextNoteSprite:ChartEditorNoteSprite = renderedNotes.recycle(ChartEditorNoteSprite);
|
||||
nextNoteSprite.parentState = this;
|
||||
nextNoteSprite.parentNoteSprite = lastNoteSprite;
|
||||
lastNoteSprite.childNoteSprite = nextNoteSprite;
|
||||
|
||||
|
@ -2306,7 +2381,7 @@ class ChartEditorState extends HaxeUIState
|
|||
var diffStepTime = Conductor.currentStepTime - oldStepTime;
|
||||
|
||||
// Move the playhead.
|
||||
playheadPosition += diffStepTime * GRID_SIZE;
|
||||
playheadPositionInPixels += diffStepTime * GRID_SIZE;
|
||||
|
||||
// We don't move the song to scroll position, or update the note sprites.
|
||||
}
|
||||
|
@ -2322,7 +2397,7 @@ class ChartEditorState extends HaxeUIState
|
|||
|
||||
// We need time in fractional steps here to allow the song to actually play.
|
||||
// Also account for a potentially offset playhead.
|
||||
scrollPosition = Conductor.currentStepTime * GRID_SIZE - playheadPosition;
|
||||
scrollPositionInPixels = Conductor.currentStepTime * GRID_SIZE - playheadPositionInPixels;
|
||||
|
||||
// DO NOT move song to scroll position here specifically.
|
||||
|
||||
|
@ -2340,12 +2415,14 @@ class ChartEditorState extends HaxeUIState
|
|||
/**
|
||||
* Handle the playback of hitsounds.
|
||||
*/
|
||||
function handleHitsounds(oldSongPosition:Float, newSongPosition:Float):Void {
|
||||
function handleHitsounds(oldSongPosition:Float, newSongPosition:Float):Void
|
||||
{
|
||||
if (!hitsoundsEnabled)
|
||||
return;
|
||||
|
||||
// Assume notes are sorted by time.
|
||||
for (noteData in currentSongChartNoteData) {
|
||||
for (noteData in currentSongChartNoteData)
|
||||
{
|
||||
if (noteData.time < oldSongPosition)
|
||||
// Note is in the past.
|
||||
continue;
|
||||
|
@ -2355,7 +2432,8 @@ class ChartEditorState extends HaxeUIState
|
|||
return;
|
||||
|
||||
// Note was just hit.
|
||||
switch (noteData.getStrumlineIndex()) {
|
||||
switch (noteData.getStrumlineIndex())
|
||||
{
|
||||
case 0: // Player
|
||||
if (hitsoundsEnabledPlayer)
|
||||
playSound(Paths.sound('funnyNoise/funnyNoise-09'));
|
||||
|
@ -2366,7 +2444,6 @@ class ChartEditorState extends HaxeUIState
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
function startAudioPlayback()
|
||||
{
|
||||
if (audioInstTrack != null)
|
||||
|
@ -2429,40 +2506,40 @@ class ChartEditorState extends HaxeUIState
|
|||
|
||||
function placeNoteAtPlayhead(column:Int):Void
|
||||
{
|
||||
var gridSnappedPlayheadPos = scrollPosition - (scrollPosition % GRID_SIZE);
|
||||
var gridSnappedPlayheadPos = scrollPositionInPixels - (scrollPositionInPixels % GRID_SIZE);
|
||||
}
|
||||
|
||||
function set_scrollPosition(value:Float):Float
|
||||
function set_scrollPositionInPixels(value:Float):Float
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
// If we're scrolling up, and we hit the top,
|
||||
// but the playhead is in the middle, move the playhead up.
|
||||
if (playheadPosition > 0)
|
||||
if (playheadPositionInPixels > 0)
|
||||
{
|
||||
var amount = scrollPosition - value;
|
||||
playheadPosition -= amount;
|
||||
var amount = scrollPositionInPixels - value;
|
||||
playheadPositionInPixels -= amount;
|
||||
}
|
||||
|
||||
value = 0;
|
||||
}
|
||||
|
||||
if (value > songLength)
|
||||
value = songLength;
|
||||
if (value > songLengthInPixels)
|
||||
value = songLengthInPixels;
|
||||
|
||||
if (value == scrollPosition)
|
||||
if (value == scrollPositionInPixels)
|
||||
return value;
|
||||
|
||||
this.scrollPosition = value;
|
||||
this.scrollPositionInPixels = value;
|
||||
|
||||
// Move the grid sprite to the correct position.
|
||||
if (isViewDownscroll)
|
||||
{
|
||||
gridTiledSprite.y = -scrollPosition + (MENU_BAR_HEIGHT + GRID_TOP_PAD);
|
||||
gridTiledSprite.y = -scrollPositionInPixels + (MENU_BAR_HEIGHT + GRID_TOP_PAD);
|
||||
}
|
||||
else
|
||||
{
|
||||
gridTiledSprite.y = -scrollPosition + (MENU_BAR_HEIGHT + GRID_TOP_PAD);
|
||||
gridTiledSprite.y = -scrollPositionInPixels + (MENU_BAR_HEIGHT + GRID_TOP_PAD);
|
||||
}
|
||||
// Move the rendered notes to the correct position.
|
||||
renderedNotes.setPosition(gridTiledSprite.x, gridTiledSprite.y);
|
||||
|
@ -2474,23 +2551,28 @@ class ChartEditorState extends HaxeUIState
|
|||
gridSpectrogram.setPosition(0, 0);
|
||||
}
|
||||
|
||||
return this.scrollPosition;
|
||||
return this.scrollPositionInPixels;
|
||||
}
|
||||
|
||||
function set_playheadPosition(value:Float):Float
|
||||
function get_playheadPositionInPixels():Float
|
||||
{
|
||||
return this.playheadPositionInPixels;
|
||||
}
|
||||
|
||||
function set_playheadPositionInPixels(value:Float):Float
|
||||
{
|
||||
// Make sure playhead doesn't go outside the song.
|
||||
if (value + scrollPosition < 0)
|
||||
value = -scrollPosition;
|
||||
if (value + scrollPosition > songLength)
|
||||
value = songLength - scrollPosition;
|
||||
if (value + scrollPositionInPixels < 0)
|
||||
value = -scrollPositionInPixels;
|
||||
if (value + scrollPositionInPixels > songLengthInPixels)
|
||||
value = songLengthInPixels - scrollPositionInPixels;
|
||||
|
||||
this.playheadPosition = value;
|
||||
this.playheadPositionInPixels = value;
|
||||
|
||||
// Move the playhead sprite to the correct position.
|
||||
gridPlayhead.y = this.playheadPosition + (MENU_BAR_HEIGHT + GRID_TOP_PAD);
|
||||
gridPlayhead.y = this.playheadPositionInPixels + (MENU_BAR_HEIGHT + GRID_TOP_PAD);
|
||||
|
||||
return this.playheadPosition;
|
||||
return this.playheadPositionInPixels;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2557,17 +2639,17 @@ class ChartEditorState extends HaxeUIState
|
|||
audioVocalTrackGroup.pause();
|
||||
};
|
||||
|
||||
songLength = Std.int(Conductor.getTimeInSteps(audioInstTrack.length) * GRID_SIZE);
|
||||
songLengthInPixels = Std.int(Conductor.getTimeInSteps(audioInstTrack.length) * GRID_SIZE);
|
||||
|
||||
gridTiledSprite.height = songLength;
|
||||
gridTiledSprite.height = songLengthInPixels;
|
||||
if (gridSpectrogram != null)
|
||||
{
|
||||
gridSpectrogram.setSound(audioInstTrack);
|
||||
gridSpectrogram.generateSection(0, songLengthInMs / 1000);
|
||||
}
|
||||
|
||||
scrollPosition = 0;
|
||||
playheadPosition = 0;
|
||||
scrollPositionInPixels = 0;
|
||||
playheadPositionInPixels = 0;
|
||||
moveSongToScrollPosition();
|
||||
}
|
||||
|
||||
|
@ -2637,13 +2719,12 @@ class ChartEditorState extends HaxeUIState
|
|||
this.songChartData.set(variation, SongDataParser.parseSongChartData(songId, metadata.variation));
|
||||
}
|
||||
|
||||
Conductor.forceBPM(null); // Disable the forced BPM.
|
||||
Conductor.mapTimeChanges(currentSongMetadata.timeChanges);
|
||||
|
||||
loadInstrumentalFromAsset(Paths.inst(songId));
|
||||
loadVocalsFromAsset(Paths.voices(songId));
|
||||
|
||||
// Apply BPM
|
||||
|
||||
// showNotification('Loaded song ${songId}.');
|
||||
}
|
||||
|
||||
|
|
|
@ -111,8 +111,8 @@ class ChartEditorThemeHandler
|
|||
|
||||
// 2 * (Strumline Size) + 1 grid squares wide, by (4 * quarter notes per measure) grid squares tall.
|
||||
// This gets reused to fill the screen.
|
||||
var gridWidth = ChartEditorState.GRID_SIZE * (ChartEditorState.STRUMLINE_SIZE * 2 + 1);
|
||||
var gridHeight = ChartEditorState.GRID_SIZE * (STEPS_PER_BEAT * BEATS_PER_MEASURE);
|
||||
var gridWidth:Int = Std.int(ChartEditorState.GRID_SIZE * (ChartEditorState.STRUMLINE_SIZE * 2 + 1));
|
||||
var gridHeight:Int = Std.int(ChartEditorState.GRID_SIZE * (STEPS_PER_BEAT * BEATS_PER_MEASURE));
|
||||
state.gridBitmap = FlxGridOverlay.createGrid(ChartEditorState.GRID_SIZE, ChartEditorState.GRID_SIZE, gridWidth, gridHeight, true, gridColor1,
|
||||
gridColor2);
|
||||
|
||||
|
@ -190,6 +190,11 @@ class ChartEditorThemeHandler
|
|||
// Divider at 2 * (Strumline Size)
|
||||
var dividerLineBX = ChartEditorState.GRID_SIZE * (ChartEditorState.STRUMLINE_SIZE * 2) - (GRID_STRUMLINE_DIVIDER_WIDTH / 2);
|
||||
state.gridBitmap.fillRect(new Rectangle(dividerLineBX, 0, GRID_STRUMLINE_DIVIDER_WIDTH, state.gridBitmap.height), gridStrumlineDividerColor);
|
||||
|
||||
if (state.gridTiledSprite != null) {
|
||||
state.gridTiledSprite.loadGraphic(state.gridBitmap);
|
||||
}
|
||||
// Else, gridTiledSprite will be built later.
|
||||
}
|
||||
|
||||
static function updateSelectionSquare(state:ChartEditorState):Void
|
||||
|
|
389
source/funkin/util/SystemUtil.hx
Normal file
389
source/funkin/util/SystemUtil.hx
Normal file
|
@ -0,0 +1,389 @@
|
|||
package funkin.util;
|
||||
|
||||
import haxe.io.Path;
|
||||
import haxe.io.Bytes;
|
||||
import haxe.io.BytesOutput;
|
||||
import haxe.io.Eof;
|
||||
import haxe.zip.Entry;
|
||||
import haxe.zip.Writer;
|
||||
import haxe.Json;
|
||||
import haxe.Template;
|
||||
import sys.io.File;
|
||||
import sys.io.Process;
|
||||
import sys.FileSystem;
|
||||
|
||||
class SystemUtil
|
||||
{
|
||||
public static var hostArchitecture(get, never):HostArchitecture;
|
||||
public static var hostPlatform(get, never):HostPlatform;
|
||||
public static var processorCores(get, never):Int;
|
||||
private static var _hostArchitecture:HostArchitecture;
|
||||
private static var _hostPlatform:HostPlatform;
|
||||
private static var _processorCores:Int = 0;
|
||||
|
||||
private static function get_hostPlatform():HostPlatform
|
||||
{
|
||||
if (_hostPlatform == null)
|
||||
{
|
||||
if (new EReg("window", "i").match(Sys.systemName()))
|
||||
{
|
||||
_hostPlatform = WINDOWS;
|
||||
}
|
||||
else if (new EReg("linux", "i").match(Sys.systemName()))
|
||||
{
|
||||
_hostPlatform = LINUX;
|
||||
}
|
||||
else if (new EReg("mac", "i").match(Sys.systemName()))
|
||||
{
|
||||
_hostPlatform = MAC;
|
||||
}
|
||||
|
||||
trace("", " - \x1b[1mDetected host platform:\x1b[0m " + Std.string(_hostPlatform).toUpperCase());
|
||||
}
|
||||
|
||||
return _hostPlatform;
|
||||
}
|
||||
|
||||
private static function get_hostArchitecture():HostArchitecture
|
||||
{
|
||||
if (_hostArchitecture == null)
|
||||
{
|
||||
switch (hostPlatform)
|
||||
{
|
||||
case WINDOWS:
|
||||
var architecture = Sys.getEnv("PROCESSOR_ARCHITECTURE");
|
||||
var wow64Architecture = Sys.getEnv("PROCESSOR_ARCHITEW6432");
|
||||
|
||||
if (architecture.indexOf("64") > -1 || wow64Architecture != null && wow64Architecture.indexOf("64") > -1)
|
||||
{
|
||||
_hostArchitecture = X64;
|
||||
}
|
||||
else
|
||||
{
|
||||
_hostArchitecture = X86;
|
||||
}
|
||||
|
||||
case LINUX, MAC:
|
||||
#if nodejs
|
||||
switch (js.Node.process.arch)
|
||||
{
|
||||
case "arm":
|
||||
_hostArchitecture = ARMV7;
|
||||
|
||||
case "x64":
|
||||
_hostArchitecture = X64;
|
||||
|
||||
default:
|
||||
_hostArchitecture = X86;
|
||||
}
|
||||
#else
|
||||
var process = new Process("uname", ["-m"]);
|
||||
var output = process.stdout.readAll().toString();
|
||||
var error = process.stderr.readAll().toString();
|
||||
process.exitCode();
|
||||
process.close();
|
||||
|
||||
if (output.indexOf("armv6") > -1)
|
||||
{
|
||||
_hostArchitecture = ARMV6;
|
||||
}
|
||||
else if (output.indexOf("armv7") > -1)
|
||||
{
|
||||
_hostArchitecture = ARMV7;
|
||||
}
|
||||
else if (output.indexOf("64") > -1)
|
||||
{
|
||||
_hostArchitecture = X64;
|
||||
}
|
||||
else
|
||||
{
|
||||
_hostArchitecture = X86;
|
||||
}
|
||||
#end
|
||||
|
||||
default:
|
||||
_hostArchitecture = ARMV6;
|
||||
}
|
||||
|
||||
trace("", " - \x1b[1mDetected host architecture:\x1b[0m " + Std.string(_hostArchitecture).toUpperCase());
|
||||
}
|
||||
|
||||
return _hostArchitecture;
|
||||
}
|
||||
|
||||
private static function get_processorCores():Int
|
||||
{
|
||||
if (_processorCores < 1)
|
||||
{
|
||||
var result = null;
|
||||
|
||||
if (hostPlatform == WINDOWS)
|
||||
{
|
||||
var env = Sys.getEnv("NUMBER_OF_PROCESSORS");
|
||||
|
||||
if (env != null)
|
||||
{
|
||||
result = env;
|
||||
}
|
||||
}
|
||||
else if (hostPlatform == LINUX)
|
||||
{
|
||||
result = runProcess("", "nproc", null, true, true, true);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
var cpuinfo = runProcess("", "cat", ["/proc/cpuinfo"], true, true, true);
|
||||
|
||||
if (cpuinfo != null)
|
||||
{
|
||||
var split = cpuinfo.split("processor");
|
||||
result = Std.string(split.length - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (hostPlatform == MAC)
|
||||
{
|
||||
var cores = ~/Total Number of Cores: (\d+)/;
|
||||
var output = runProcess("", "/usr/sbin/system_profiler", ["-detailLevel", "full", "SPHardwareDataType"]);
|
||||
|
||||
if (cores.match(output))
|
||||
{
|
||||
result = cores.matched(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (result == null || Std.parseInt(result) < 1)
|
||||
{
|
||||
_processorCores = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_processorCores = Std.parseInt(result);
|
||||
}
|
||||
}
|
||||
|
||||
return _processorCores;
|
||||
}
|
||||
|
||||
public static function runProcess(path:String, command:String, args:Array<String> = null, waitForOutput:Bool = true, safeExecute:Bool = true,
|
||||
ignoreErrors:Bool = false, print:Bool = false, returnErrorValue:Bool = false):String
|
||||
{
|
||||
if (print)
|
||||
{
|
||||
var message = command;
|
||||
|
||||
if (args != null)
|
||||
{
|
||||
for (arg in args)
|
||||
{
|
||||
if (arg.indexOf(" ") > -1)
|
||||
{
|
||||
message += " \"" + arg + "\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
message += " " + arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Sys.println(message);
|
||||
}
|
||||
|
||||
#if (haxe_ver < "3.3.0")
|
||||
command = Path.escape(command);
|
||||
#end
|
||||
|
||||
if (safeExecute)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (path != null
|
||||
&& path != ""
|
||||
&& !FileSystem.exists(FileSystem.fullPath(path))
|
||||
&& !FileSystem.exists(FileSystem.fullPath(new Path(path).dir)))
|
||||
{
|
||||
trace("The specified target path \"" + path + "\" does not exist");
|
||||
}
|
||||
|
||||
return _runProcess(path, command, args, waitForOutput, safeExecute, ignoreErrors, returnErrorValue);
|
||||
}
|
||||
catch (e:Dynamic)
|
||||
{
|
||||
if (!ignoreErrors)
|
||||
{
|
||||
trace("", e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return _runProcess(path, command, args, waitForOutput, safeExecute, ignoreErrors, returnErrorValue);
|
||||
}
|
||||
}
|
||||
|
||||
private static function _runProcess(path:String, command:String, args:Null<Array<String>>, waitForOutput:Bool, safeExecute:Bool, ignoreErrors:Bool,
|
||||
returnErrorValue:Bool):String
|
||||
{
|
||||
var oldPath:String = "";
|
||||
|
||||
if (path != null && path != "")
|
||||
{
|
||||
trace("", " - \x1b[1mChanging directory:\x1b[0m " + path + "");
|
||||
|
||||
oldPath = Sys.getCwd();
|
||||
Sys.setCwd(path);
|
||||
}
|
||||
|
||||
var argString = "";
|
||||
|
||||
if (args != null)
|
||||
{
|
||||
for (arg in args)
|
||||
{
|
||||
if (arg.indexOf(" ") > -1)
|
||||
{
|
||||
argString += " \"" + arg + "\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
argString += " " + arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trace("", " - \x1b[1mRunning process:\x1b[0m " + command + argString);
|
||||
|
||||
var output = "";
|
||||
var result = 0;
|
||||
|
||||
var process:Process;
|
||||
|
||||
if (args != null && args.length > 0)
|
||||
{
|
||||
process = new Process(command, args);
|
||||
}
|
||||
else
|
||||
{
|
||||
process = new Process(command);
|
||||
}
|
||||
|
||||
if (waitForOutput)
|
||||
{
|
||||
var buffer = new BytesOutput();
|
||||
var waiting = true;
|
||||
|
||||
while (waiting)
|
||||
{
|
||||
try
|
||||
{
|
||||
var current = process.stdout.readAll(1024);
|
||||
buffer.write(current);
|
||||
|
||||
if (current.length == 0)
|
||||
{
|
||||
waiting = false;
|
||||
}
|
||||
}
|
||||
catch (e:Eof)
|
||||
{
|
||||
waiting = false;
|
||||
}
|
||||
}
|
||||
|
||||
result = process.exitCode();
|
||||
|
||||
output = buffer.getBytes().toString();
|
||||
|
||||
if (output == "")
|
||||
{
|
||||
var error = process.stderr.readAll().toString();
|
||||
process.close();
|
||||
|
||||
if (result != 0 || error != "")
|
||||
{
|
||||
if (ignoreErrors)
|
||||
{
|
||||
output = error;
|
||||
}
|
||||
else if (!safeExecute)
|
||||
{
|
||||
throw error;
|
||||
}
|
||||
else
|
||||
{
|
||||
trace(error);
|
||||
}
|
||||
|
||||
if (returnErrorValue)
|
||||
{
|
||||
return output;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*if (error != "") {
|
||||
trace (error);
|
||||
}*/
|
||||
}
|
||||
else
|
||||
{
|
||||
process.close();
|
||||
}
|
||||
}
|
||||
|
||||
if (oldPath != "")
|
||||
{
|
||||
Sys.setCwd(oldPath);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public static function getTempDirectory(extension:String = ""):String
|
||||
{
|
||||
#if (flash || html5)
|
||||
return null;
|
||||
#else
|
||||
var path = "";
|
||||
|
||||
if (hostPlatform == WINDOWS)
|
||||
{
|
||||
path = Sys.getEnv("TEMP");
|
||||
}
|
||||
else
|
||||
{
|
||||
path = Sys.getEnv("TMPDIR");
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
path = "/tmp";
|
||||
}
|
||||
}
|
||||
|
||||
path = Path.join([path, "Funkin"]);
|
||||
|
||||
return path;
|
||||
#end
|
||||
}
|
||||
}
|
||||
|
||||
enum HostArchitecture
|
||||
{
|
||||
ARMV6;
|
||||
ARMV7;
|
||||
X86;
|
||||
X64;
|
||||
}
|
||||
|
||||
@:enum abstract HostPlatform(String) from String to String
|
||||
{
|
||||
public var WINDOWS = "windows";
|
||||
public var MAC = "mac";
|
||||
public var LINUX = "linux";
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue