its not done dumbass
This commit is contained in:
@@ -1,246 +0,0 @@
|
|||||||
package funkin.backend.system.macros;
|
|
||||||
|
|
||||||
using StringTools;
|
|
||||||
class SoftcodedClassMacro {
|
|
||||||
#if macro
|
|
||||||
private static var nonAllowedSuffixes:Array<String> = ["__Softcoded", "_HSC", "_HSX", "_Impl_"];
|
|
||||||
public static function init() {
|
|
||||||
Compiler.addGlobalMetadata('funkin.game.cutscenes', '@:build(funkin.backend.system.macros.SoftcodedClassMacro.build())');
|
|
||||||
Compiler.addGlobalMetadata('funkin.game', '@:build(funkin.backend.system.macros.SoftcodedClassMacro.build())');
|
|
||||||
Compiler.addGlobalMetadata('funkin.menus', '@:build(funkin.backend.system.macros.SoftcodedClassMacro.build())');
|
|
||||||
Compiler.addGlobalMetadata('funkin.options', '@:build(funkin.backend.system.macros.SoftcodedClassMacro.build())');
|
|
||||||
Compiler.addGlobalMetadata('funkin.backend.scripting', '@:build(funkin.backend.system.macros.SoftcodedClassMacro.build())');
|
|
||||||
Compiler.addGlobalMetadata('funkin.backend.shaders', '@:build(funkin.backend.system.macros.SoftcodedClassMacro.build())');
|
|
||||||
Compiler.addGlobalMetadata('flixel', '@:build(funkin.backend.system.macros.SoftcodedClassMacro.build())', false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function build():Array<Field> {
|
|
||||||
var fields = Context.getBuildFields();
|
|
||||||
var cl = Context.getLocalClass();
|
|
||||||
|
|
||||||
if (cl != null) {
|
|
||||||
var scriptClassType = TPath({
|
|
||||||
pack: ['funkin', 'scripting'],
|
|
||||||
name: 'Script',
|
|
||||||
sub: 'ScriptClass'
|
|
||||||
});
|
|
||||||
|
|
||||||
var funcs:Array<Field> = [];
|
|
||||||
funcs.push({
|
|
||||||
pos: Context.currentPos(),
|
|
||||||
name: '__scriptClass',
|
|
||||||
kind: FVar(scriptClassType, macro null)
|
|
||||||
});
|
|
||||||
var c = cl.get();
|
|
||||||
c.isPrivate = false;
|
|
||||||
switch(c.kind) {
|
|
||||||
case KNormal:
|
|
||||||
// do nothing
|
|
||||||
default:
|
|
||||||
return fields;
|
|
||||||
}
|
|
||||||
if (c.isPrivate || c.isInterface || c.isFinal || c.isExtern || c.isAbstract) return fields;
|
|
||||||
|
|
||||||
for(s in nonAllowedSuffixes)
|
|
||||||
if (c.name.endsWith(s))
|
|
||||||
return fields;
|
|
||||||
if (c.params.length > 0) return fields; // NOT SUPPORTED
|
|
||||||
if (c.isAbstract) return fields;
|
|
||||||
|
|
||||||
for(m in c.meta.get()) {
|
|
||||||
switch(m.name) {
|
|
||||||
case ":final", ":noSoftcodedExtend":
|
|
||||||
return fields;
|
|
||||||
default:
|
|
||||||
// cool
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var shadowClass = macro class {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// var fixedPack = [for(p in c.pack) if (p.startsWith("_")) p.substr(1) else p];
|
|
||||||
|
|
||||||
shadowClass.name = '${c.name}__Softcoded';
|
|
||||||
shadowClass.fields = funcs;
|
|
||||||
shadowClass.pack = c.pack.copy();
|
|
||||||
shadowClass.kind = TDClass({
|
|
||||||
pack: c.pack.copy(),
|
|
||||||
name: c.name
|
|
||||||
}, [], false, false, false);
|
|
||||||
|
|
||||||
var addedFields:Array<String> = [];
|
|
||||||
|
|
||||||
#if !display
|
|
||||||
for(f in [for(f in fields) f]) {
|
|
||||||
var valid = true;
|
|
||||||
if (f.access != null) for(e in f.access) {
|
|
||||||
switch (e) {
|
|
||||||
case AStatic | ADynamic | AInline | AMacro | AFinal | AExtern | AAbstract:
|
|
||||||
valid = false;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!valid) continue;
|
|
||||||
|
|
||||||
switch(f.kind) {
|
|
||||||
case FFun(fun):
|
|
||||||
if (fun.params != null && fun.params.length > 0) continue;
|
|
||||||
var funcExpr = macro {
|
|
||||||
${{
|
|
||||||
pos: Context.currentPos(),
|
|
||||||
expr: ECall({
|
|
||||||
pos: Context.currentPos(),
|
|
||||||
expr: EField({
|
|
||||||
pos: Context.currentPos(),
|
|
||||||
expr: EConst(CIdent("super"))
|
|
||||||
}, f.name)
|
|
||||||
}, fun.args != null ? [for(a in fun.args) {
|
|
||||||
pos: Context.currentPos(),
|
|
||||||
expr: EConst(CIdent(a.name))
|
|
||||||
}] : [])
|
|
||||||
}};
|
|
||||||
};
|
|
||||||
|
|
||||||
var isVoid = fun.ret.match(TPath({name: "Void"}));
|
|
||||||
|
|
||||||
if (!isVoid)
|
|
||||||
funcExpr = macro return ${funcExpr};
|
|
||||||
|
|
||||||
var accessors = [];
|
|
||||||
if (f.access != null) for(f in f.access) accessors.push(f);
|
|
||||||
accessors.remove(AOverride);
|
|
||||||
|
|
||||||
if (f.name == "new") {
|
|
||||||
var constructorExpr = macro {
|
|
||||||
${{
|
|
||||||
expr: ECall({
|
|
||||||
pos: Context.currentPos(),
|
|
||||||
expr: EConst(CIdent("super"))
|
|
||||||
}, fun.args != null ? [for(a in fun.args) {
|
|
||||||
pos: Context.currentPos(),
|
|
||||||
expr: EConst(CIdent(a.name))
|
|
||||||
}] : []),
|
|
||||||
pos: Context.currentPos()
|
|
||||||
}}
|
|
||||||
|
|
||||||
__scriptClass = scrObj;
|
|
||||||
|
|
||||||
__scriptClass.call("new", ${{
|
|
||||||
pos: Context.currentPos(),
|
|
||||||
expr: EArrayDecl([for(a in fun.args) {
|
|
||||||
pos: Context.currentPos(),
|
|
||||||
expr: EConst(CIdent(a.name))
|
|
||||||
}])
|
|
||||||
}}, this);
|
|
||||||
|
|
||||||
}
|
|
||||||
var func:Function = {
|
|
||||||
expr: constructorExpr,
|
|
||||||
args: [for(a in fun.args) a]
|
|
||||||
};
|
|
||||||
func.args.insert(0, {
|
|
||||||
name: "scrObj",
|
|
||||||
type: scriptClassType
|
|
||||||
});
|
|
||||||
funcs.push({
|
|
||||||
pos: Context.currentPos(),
|
|
||||||
name: 'new',
|
|
||||||
kind: FFun(func),
|
|
||||||
access: [for(a in accessors) a]
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
var printer = new Printer();
|
|
||||||
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
var func:Function = {
|
|
||||||
expr: funcExpr,
|
|
||||||
args: fun.args
|
|
||||||
};
|
|
||||||
funcs.push({
|
|
||||||
pos: Context.currentPos(),
|
|
||||||
name: '__super__${f.name}',
|
|
||||||
kind: FFun(func),
|
|
||||||
access: [for(a in accessors) a]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
accessors.push(AOverride);
|
|
||||||
|
|
||||||
var overrideFuncExpr = isVoid ? macro {
|
|
||||||
var fieldName = ${{
|
|
||||||
pos: Context.currentPos(),
|
|
||||||
expr: EConst(CString(f.name, DoubleQuotes))
|
|
||||||
}};
|
|
||||||
if (__scriptClass != null && __scriptClass.hasField(fieldName) && Reflect.isFunction(__scriptClass.get(fieldName))) {
|
|
||||||
__scriptClass.call(fieldName, ${{
|
|
||||||
pos: Context.currentPos(),
|
|
||||||
expr: EArrayDecl([for(a in fun.args) {
|
|
||||||
pos: Context.currentPos(),
|
|
||||||
expr: EConst(CIdent(a.name))
|
|
||||||
}])
|
|
||||||
}}, this);
|
|
||||||
} else ${funcExpr}
|
|
||||||
} : macro {
|
|
||||||
var fieldName = ${{
|
|
||||||
pos: Context.currentPos(),
|
|
||||||
expr: EConst(CString(f.name, DoubleQuotes))
|
|
||||||
}};
|
|
||||||
if (__scriptClass != null && __scriptClass.hasField(fieldName) && Reflect.isFunction(__scriptClass.get(fieldName))) {
|
|
||||||
return __scriptClass.call(fieldName, ${{
|
|
||||||
pos: Context.currentPos(),
|
|
||||||
expr: EArrayDecl([for(a in fun.args) {
|
|
||||||
pos: Context.currentPos(),
|
|
||||||
expr: EConst(CIdent(a.name))
|
|
||||||
}])
|
|
||||||
}}, this);
|
|
||||||
} else ${funcExpr}
|
|
||||||
};
|
|
||||||
|
|
||||||
var overrideFunc:Function = {
|
|
||||||
expr: overrideFuncExpr,
|
|
||||||
args: fun.args
|
|
||||||
};
|
|
||||||
funcs.push({
|
|
||||||
pos: Context.currentPos(),
|
|
||||||
name: '${f.name}',
|
|
||||||
kind: FFun(overrideFunc),
|
|
||||||
access: accessors
|
|
||||||
});
|
|
||||||
|
|
||||||
default:
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
|
|
||||||
var imports = [for(i in Context.getLocalImports()) i];
|
|
||||||
imports.push({
|
|
||||||
path: [for(p in c.module.split(".")) {
|
|
||||||
pos: Context.currentPos(),
|
|
||||||
name: p
|
|
||||||
}],
|
|
||||||
mode: IAll
|
|
||||||
});
|
|
||||||
imports.push({
|
|
||||||
path: [for(p in c.module.split(".")) {
|
|
||||||
pos: Context.currentPos(),
|
|
||||||
name: p
|
|
||||||
}],
|
|
||||||
mode: INormal
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
Context.defineModule(c.module + "__Softcoded", [shadowClass], imports);
|
|
||||||
}
|
|
||||||
return fields;
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
}
|
|
||||||
@@ -138,7 +138,7 @@ typedef EventParamInfo = {
|
|||||||
|
|
||||||
enum EventParamType {
|
enum EventParamType {
|
||||||
TBool;
|
TBool;
|
||||||
TInt(?min:Int, ?max:Int);
|
TInt(?min:Int, ?max:Int, ?step:Float);
|
||||||
TFloat(?min:Int, ?max:Int, ?step:Float, ?precision:Int);
|
TFloat(?min:Int, ?max:Int, ?step:Float, ?precision:Int);
|
||||||
TString;
|
TString;
|
||||||
TArrayOfString;
|
TArrayOfString;
|
||||||
|
|||||||
@@ -27,19 +27,6 @@ class CharterEventScreen extends UISubstateWindow {
|
|||||||
FlxG.sound.music.pause(); // prevent the song from continuing
|
FlxG.sound.music.pause(); // prevent the song from continuing
|
||||||
|
|
||||||
iconsPanel = new FlxGroup();
|
iconsPanel = new FlxGroup();
|
||||||
|
|
||||||
for(k=>e in chartEvent.events) {
|
|
||||||
var butt = new UIButton(windowSpr.x + 1, windowSpr.y + 31 + (k*30), "", function() {
|
|
||||||
changeTab(k);
|
|
||||||
});
|
|
||||||
butt.bWidth = butt.bHeight = 30;
|
|
||||||
iconsPanel.add(butt);
|
|
||||||
|
|
||||||
var icon = CharterEvent.generateEventIcon(e);
|
|
||||||
icon.setPosition(butt.x + ((butt.bWidth - icon.width) / 2), butt.y + ((butt.bHeight - icon.height) / 2));
|
|
||||||
iconsPanel.add(icon);
|
|
||||||
}
|
|
||||||
|
|
||||||
add(iconsPanel);
|
add(iconsPanel);
|
||||||
|
|
||||||
paramsPanel = new FlxGroup();
|
paramsPanel = new FlxGroup();
|
||||||
@@ -55,6 +42,7 @@ class CharterEventScreen extends UISubstateWindow {
|
|||||||
|
|
||||||
public function changeTab(id:Int) {
|
public function changeTab(id:Int) {
|
||||||
saveCurTab();
|
saveCurTab();
|
||||||
|
|
||||||
|
|
||||||
// destroy old elements
|
// destroy old elements
|
||||||
paramsFields = [];
|
paramsFields = [];
|
||||||
@@ -83,8 +71,32 @@ class CharterEventScreen extends UISubstateWindow {
|
|||||||
paramsFields.push(textBox);
|
paramsFields.push(textBox);
|
||||||
case TBool:
|
case TBool:
|
||||||
var checkbox = new UICheckbox(eventName.x, y, param.name, cast curEvent.params[k]);
|
var checkbox = new UICheckbox(eventName.x, y, param.name, cast curEvent.params[k]);
|
||||||
|
y += checkbox.height + 10;
|
||||||
paramsPanel.add(checkbox);
|
paramsPanel.add(checkbox);
|
||||||
paramsFields.push(checkbox);
|
paramsFields.push(checkbox);
|
||||||
|
case TInt(min, max, step):
|
||||||
|
var label:UIText = new UIText(eventName.x, y, 0, param.name);
|
||||||
|
y += label.height + 4;
|
||||||
|
paramsPanel.add(label);
|
||||||
|
|
||||||
|
var numericStepper = new UINumericStepper(eventName.x, y, cast curEvent.params[k], step.getDefault(1), 0, min, max);
|
||||||
|
y += numericStepper.height + 10;
|
||||||
|
paramsPanel.add(numericStepper);
|
||||||
|
paramsFields.push(numericStepper);
|
||||||
|
case TFloat(min, max, step, precision):
|
||||||
|
var label:UIText = new UIText(eventName.x, y, 0, param.name);
|
||||||
|
y += label.height + 4;
|
||||||
|
paramsPanel.add(label);
|
||||||
|
|
||||||
|
var numericStepper = new UINumericStepper(eventName.x, y, cast curEvent.params[k], step.getDefault(1), precision, min, max);
|
||||||
|
y += numericStepper.height + 10;
|
||||||
|
paramsPanel.add(numericStepper);
|
||||||
|
paramsFields.push(numericStepper);
|
||||||
|
case TStrumLine:
|
||||||
|
var dropdown = new UIDropDown(eventName.x, y, 320, 32, [for(k=>s in cast(FlxG.state, Charter).strumLines.members) 'Strumline #${k+1} (${s.strumLine.characters[0]})'], cast curEvent.params[k]);
|
||||||
|
y += dropdown.height + 10;
|
||||||
|
paramsPanel.add(dropdown);
|
||||||
|
paramsFields.push(dropdown);
|
||||||
default:
|
default:
|
||||||
// none
|
// none
|
||||||
paramsFields.push(null);
|
paramsFields.push(null);
|
||||||
@@ -93,19 +105,49 @@ class CharterEventScreen extends UISubstateWindow {
|
|||||||
} else
|
} else
|
||||||
curEvent = -1;
|
curEvent = -1;
|
||||||
|
|
||||||
|
refreshIcons();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function refreshIcons() {
|
||||||
|
while(iconsPanel.members.length > 0)
|
||||||
|
iconsPanel.remove(iconsPanel.members[0], true).destroy();
|
||||||
|
|
||||||
|
for(k=>e in chartEvent.events) {
|
||||||
|
var butt = new UIButton(windowSpr.x + 1, windowSpr.y + 31 + (k*30), "", function() {
|
||||||
|
changeTab(k);
|
||||||
|
});
|
||||||
|
butt.bWidth = butt.bHeight = 30;
|
||||||
|
butt.visible = (k != curEvent);
|
||||||
|
iconsPanel.add(butt);
|
||||||
|
|
||||||
|
var icon = CharterEvent.generateEventIcon(e);
|
||||||
|
icon.setPosition(butt.x + ((butt.bWidth - icon.width) / 2), butt.y + ((butt.bHeight - icon.height) / 2));
|
||||||
|
iconsPanel.add(icon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function saveCurTab() {
|
public function saveCurTab() {
|
||||||
if (curEvent < 0) return;
|
if (curEvent < 0) return;
|
||||||
|
|
||||||
chartEvent.events[curEvent].params = [for(p in paramsFields) {
|
chartEvent.events[curEvent].params = [
|
||||||
if (p is UITextBox)
|
for(p in paramsFields) {
|
||||||
cast(p, UITextBox).label.text;
|
if (p is UIDropDown)
|
||||||
else if (p is UICheckbox)
|
cast(p, UIDropDown).index;
|
||||||
cast(p, UICheckbox).checked;
|
else if (p is UINumericStepper) {
|
||||||
else
|
var stepper = cast(p, UINumericStepper);
|
||||||
null;
|
// int
|
||||||
}
|
if (stepper.precision == 0)
|
||||||
|
Std.int(stepper.value);
|
||||||
|
else
|
||||||
|
stepper.value;
|
||||||
|
}
|
||||||
|
else if (p is UITextBox)
|
||||||
|
cast(p, UITextBox).label.text;
|
||||||
|
else if (p is UICheckbox)
|
||||||
|
cast(p, UICheckbox).checked;
|
||||||
|
else
|
||||||
|
null;
|
||||||
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ class CharterNoteGroup extends FlxTypedGroup<CharterNote> {
|
|||||||
if (FlxG.state is Charter && !FlxG.sound.music.playing)
|
if (FlxG.state is Charter && !FlxG.sound.music.playing)
|
||||||
curStep = cast(FlxG.state, Charter).conductorFollowerSpr.y / 40;
|
curStep = cast(FlxG.state, Charter).conductorFollowerSpr.y / 40;
|
||||||
|
|
||||||
var begin = SortedArrayUtil.binarySearch(members, curStep - max, getVarForEach);
|
var begin = SortedArrayUtil.binarySearch(members, curStep - max, getVarForEachAdd);
|
||||||
var end = SortedArrayUtil.binarySearch(members, curStep + max, getVarForEach);
|
var end = SortedArrayUtil.binarySearch(members, curStep + max, getVarForEachRemove);
|
||||||
|
|
||||||
for(i in begin...end) {
|
for(i in begin...end) {
|
||||||
__loopSprite = members[i];
|
__loopSprite = members[i];
|
||||||
@@ -45,8 +45,10 @@ class CharterNoteGroup extends FlxTypedGroup<CharterNote> {
|
|||||||
private static function getVar(n:CharterNote)
|
private static function getVar(n:CharterNote)
|
||||||
return n.step;
|
return n.step;
|
||||||
|
|
||||||
private static function getVarForEach(n:CharterNote)
|
private static function getVarForEachAdd(n:CharterNote)
|
||||||
return n.step + n.susLength;
|
return n.step + n.susLength;
|
||||||
|
private static function getVarForEachRemove(n:CharterNote)
|
||||||
|
return n.step - n.susLength;
|
||||||
|
|
||||||
public override function draw() {
|
public override function draw() {
|
||||||
@:privateAccess var oldDefaultCameras = FlxCamera._defaultCameras;
|
@:privateAccess var oldDefaultCameras = FlxCamera._defaultCameras;
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package funkin.editors.ui;
|
||||||
|
|
||||||
|
class UIDropDown extends UISliceSprite {
|
||||||
|
public var dropButton:UIButton;
|
||||||
|
public var label:UIText;
|
||||||
|
|
||||||
|
public var index:Int = 0;
|
||||||
|
public var options:Array<String>;
|
||||||
|
|
||||||
|
public var onChange:Int->Void;
|
||||||
|
|
||||||
|
var curMenu:UIContextMenu = null;
|
||||||
|
|
||||||
|
public function new(x:Float, y:Float, width:Int = 320, height:Int = 32, options:Array<String>, index:Int = 0) {
|
||||||
|
super(x, y, width - height, height, 'editors/ui/inputbox'); // using same sprite cause fuck you
|
||||||
|
|
||||||
|
this.options = options;
|
||||||
|
this.index = index;
|
||||||
|
|
||||||
|
label = new UIText(0, 0, width - height, options[index]);
|
||||||
|
members.push(label);
|
||||||
|
|
||||||
|
dropButton = new UIButton(0, 0, "V", null, height, height);
|
||||||
|
members.push(dropButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setOption(newIndex:Int) {
|
||||||
|
if (index != (index = newIndex)) {
|
||||||
|
label.text = options[index];
|
||||||
|
if (onChange != null)
|
||||||
|
onChange(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override function update(elapsed:Float) {
|
||||||
|
|
||||||
|
var opened = curMenu.contextMenuOpened();
|
||||||
|
framesOffset = (opened || (hovered && FlxG.mouse.pressed)) ? 18 : (hovered ? 9 : 0);
|
||||||
|
if (FlxG.mouse.justReleased && (hovered || dropButton.hovered)) {
|
||||||
|
if (opened)
|
||||||
|
UIState.state.curContextMenu.preventOutOfBoxClickDeletion();
|
||||||
|
else
|
||||||
|
openContextMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
super.update(elapsed);
|
||||||
|
|
||||||
|
label.follow(this, 4, Std.int((bHeight - label.height) / 2));
|
||||||
|
dropButton.follow(this, bWidth - bHeight, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function openContextMenu() {
|
||||||
|
var screenPos = getScreenPosition(null, __lastDrawCameras[0] == null ? FlxG.camera : __lastDrawCameras[0]);
|
||||||
|
curMenu = UIState.state.openContextMenu([
|
||||||
|
for(k=>o in options) {
|
||||||
|
icon: (k == index) ? 1 : 0,
|
||||||
|
label: o
|
||||||
|
}
|
||||||
|
], function(_, i, _) {
|
||||||
|
setOption(i);
|
||||||
|
}, screenPos.x, screenPos.y + bHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package funkin.editors.ui;
|
||||||
|
|
||||||
|
class UINumericStepper extends UITextBox {
|
||||||
|
public var value(default, set):Float;
|
||||||
|
public var precision:Int = 0;
|
||||||
|
public var min:Null<Float> = null;
|
||||||
|
public var max:Null<Float> = null;
|
||||||
|
public var step:Float = 1;
|
||||||
|
|
||||||
|
public function new(x:Float, y:Float, value:Float = 0, step:Float = 1, precision:Int = 0, ?min:Float, ?max:Float, w:Int = 180, h:Int = 32) {
|
||||||
|
super(x, y, "", w - h, h, false);
|
||||||
|
|
||||||
|
onChange = __onChange;
|
||||||
|
|
||||||
|
this.precision = precision;
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
this.step = step;
|
||||||
|
|
||||||
|
set_value(value);
|
||||||
|
|
||||||
|
// TODO: add stepper buttons
|
||||||
|
}
|
||||||
|
|
||||||
|
private function __onChange(text:String) {
|
||||||
|
var f = Std.parseFloat(text);
|
||||||
|
if (Math.isNaN(f))
|
||||||
|
return;
|
||||||
|
value = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function set_value(v:Float) {
|
||||||
|
if (min != null && max != null) {
|
||||||
|
v = FlxMath.bound(v, min, max);
|
||||||
|
} else if (min != null) {
|
||||||
|
v = Math.max(v, min);
|
||||||
|
} else if (max != null) {
|
||||||
|
v = Math.min(v, max);
|
||||||
|
}
|
||||||
|
label.text = Std.string(FlxMath.roundDecimal(v, precision));
|
||||||
|
return value = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -119,7 +119,7 @@ class UIState extends MusicBeatState {
|
|||||||
state.persistentDraw = true;
|
state.persistentDraw = true;
|
||||||
state.persistentUpdate = true;
|
state.persistentUpdate = true;
|
||||||
|
|
||||||
openSubState(curContextMenu = new UIContextMenu(options, callback, x.getDefault(__mousePos.x), y.getDefault(__mousePos.y)));
|
state.openSubState(curContextMenu = new UIContextMenu(options, callback, x.getDefault(__mousePos.x), y.getDefault(__mousePos.y)));
|
||||||
return curContextMenu;
|
return curContextMenu;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,6 +13,10 @@ class UITextBox extends UISliceSprite implements IUIFocusable {
|
|||||||
public var multiline:Bool = false;
|
public var multiline:Bool = false;
|
||||||
public var caretSpr:FlxSprite;
|
public var caretSpr:FlxSprite;
|
||||||
|
|
||||||
|
public var onChange:String->Void;
|
||||||
|
|
||||||
|
var __wasFocused:Bool = false;
|
||||||
|
|
||||||
public function new(x:Float, y:Float, text:String = "", width:Int = 320, height:Int = 32, multiline:Bool = false) {
|
public function new(x:Float, y:Float, text:String = "", width:Int = 320, height:Int = 32, multiline:Bool = false) {
|
||||||
super(x, y, width, height, 'editors/ui/inputbox');
|
super(x, y, width, height, 'editors/ui/inputbox');
|
||||||
|
|
||||||
@@ -25,30 +29,38 @@ class UITextBox extends UISliceSprite implements IUIFocusable {
|
|||||||
caretSpr.updateHitbox();
|
caretSpr.updateHitbox();
|
||||||
members.push(caretSpr);
|
members.push(caretSpr);
|
||||||
this.multiline = multiline;
|
this.multiline = multiline;
|
||||||
|
position = text.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
var cacheRect:Rectangle = new Rectangle();
|
var cacheRect:Rectangle = new Rectangle();
|
||||||
|
|
||||||
public override function update(elapsed:Float) {
|
public override function update(elapsed:Float) {
|
||||||
super.update(elapsed);
|
if (hovered && FlxG.mouse.justReleased && __lastDrawCameras.length > 0) {
|
||||||
var off = multiline ? 4 : ((bHeight - label.height) / 2);
|
|
||||||
label.follow(this, 4, off);
|
|
||||||
|
|
||||||
if (hovered && FlxG.mouse.justReleased) {
|
|
||||||
// get caret pos
|
// get caret pos
|
||||||
var pos = FlxG.mouse.getScreenPosition(camera, FlxPoint.get());
|
var pos = FlxG.mouse.getScreenPosition(__lastDrawCameras[0], FlxPoint.get());
|
||||||
pos.x -= label.x;
|
pos.x -= label.x;
|
||||||
pos.y -= label.y;
|
pos.y -= label.y;
|
||||||
|
|
||||||
var index = label.textField.getCharIndexAtPoint(pos.x, pos.y);
|
if (pos.x < 0)
|
||||||
if (index > -1)
|
position = 0;
|
||||||
position = index;
|
else {
|
||||||
|
var index = label.textField.getCharIndexAtPoint(pos.x, pos.y);
|
||||||
|
if (index > -1)
|
||||||
|
position = index;
|
||||||
|
else
|
||||||
|
position = label.text.length;
|
||||||
|
}
|
||||||
|
|
||||||
pos.put();
|
pos.put();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
super.update(elapsed);
|
||||||
|
var off = multiline ? 4 : ((bHeight - label.height) / 2);
|
||||||
|
label.follow(this, 4, off);
|
||||||
framesOffset = (focused ? 18 : (hovered ? 9 : 0));
|
framesOffset = (focused ? 18 : (hovered ? 9 : 0));
|
||||||
@:privateAccess {
|
@:privateAccess {
|
||||||
if (focused) {
|
if (focused) {
|
||||||
|
__wasFocused = true;
|
||||||
caretSpr.alpha = (FlxG.game.ticks % 666) >= 333 ? 1 : 0;
|
caretSpr.alpha = (FlxG.game.ticks % 666) >= 333 ? 1 : 0;
|
||||||
|
|
||||||
var curPos = switch(position) {
|
var curPos = switch(position) {
|
||||||
@@ -66,6 +78,11 @@ class UITextBox extends UISliceSprite implements IUIFocusable {
|
|||||||
caretSpr.follow(this, 4 + curPos.x, off + curPos.y);
|
caretSpr.follow(this, 4 + curPos.x, off + curPos.y);
|
||||||
curPos.put();
|
curPos.put();
|
||||||
} else {
|
} else {
|
||||||
|
if (__wasFocused) {
|
||||||
|
__wasFocused = false;
|
||||||
|
if (onChange != null)
|
||||||
|
onChange(label.text);
|
||||||
|
}
|
||||||
caretSpr.alpha = 0;
|
caretSpr.alpha = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,6 +90,8 @@ class UITextBox extends UISliceSprite implements IUIFocusable {
|
|||||||
|
|
||||||
public function onKeyDown(e:KeyCode, modifier:KeyModifier) {
|
public function onKeyDown(e:KeyCode, modifier:KeyModifier) {
|
||||||
switch(e) {
|
switch(e) {
|
||||||
|
case RETURN:
|
||||||
|
focused = false;
|
||||||
case LEFT:
|
case LEFT:
|
||||||
changeSelection(-1);
|
changeSelection(-1);
|
||||||
case RIGHT:
|
case RIGHT:
|
||||||
@@ -87,7 +106,7 @@ class UITextBox extends UISliceSprite implements IUIFocusable {
|
|||||||
case END:
|
case END:
|
||||||
position = label.text.length;
|
position = label.text.length;
|
||||||
case V:
|
case V:
|
||||||
if (modifier == KeyModifier.LEFT_CTRL || modifier == KeyModifier.RIGHT_CTRL ) {
|
if (modifier == KeyModifier.LEFT_CTRL || modifier == KeyModifier.RIGHT_CTRL) {
|
||||||
// paste
|
// paste
|
||||||
var data:String = Clipboard.generalClipboard.getData(TEXT_FORMAT);
|
var data:String = Clipboard.generalClipboard.getData(TEXT_FORMAT);
|
||||||
if (data != null)
|
if (data != null)
|
||||||
|
|||||||
@@ -62,13 +62,11 @@ class UITopMenuButton extends UISliceSprite {
|
|||||||
|
|
||||||
public override function onHovered() {
|
public override function onHovered() {
|
||||||
super.onHovered();
|
super.onHovered();
|
||||||
if (hovered) {
|
if (curMenu.contextMenuOpened()) {
|
||||||
if (curMenu.contextMenuOpened()) {
|
UIState.state.curContextMenu.preventOutOfBoxClickDeletion();
|
||||||
UIState.state.curContextMenu.preventOutOfBoxClickDeletion();
|
} else {
|
||||||
} else {
|
if ((parent != null && parent.anyMenuOpened) || FlxG.mouse.justReleased) {
|
||||||
if ((parent != null && parent.anyMenuOpened) || FlxG.mouse.justReleased) {
|
openContextMenu();
|
||||||
openContextMenu();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user