mirror of
https://github.com/Ttanasart-pt/Pixel-Composer.git
synced 2025-01-23 11:28:06 +01:00
- [3D Mesh] Fix rotation manipulation error with in euler angles unit.
This commit is contained in:
parent
be111dc314
commit
c751d80542
67 changed files with 9791 additions and 532 deletions
1221
#backups/objects/o_dialog_preference/o_dialog_preference.yy.backup0
Normal file
1221
#backups/objects/o_dialog_preference/o_dialog_preference.yy.backup0
Normal file
File diff suppressed because it is too large
Load diff
1221
#backups/objects/o_dialog_preference/o_dialog_preference.yy.backup1
Normal file
1221
#backups/objects/o_dialog_preference/o_dialog_preference.yy.backup1
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
||||||
// 2024-04-29 18:32:52
|
// 2024-05-01 08:45:28
|
||||||
#event properties (no comments/etc. here are saved)
|
#event properties (no comments/etc. here are saved)
|
||||||
parent_index = -1;
|
parent_index = -1;
|
||||||
persistent = true;
|
persistent = true;
|
||||||
|
@ -1378,110 +1378,112 @@ if(APP_SURF_OVERRIDE) { #region
|
||||||
if(winMan_isMinimized()) exit;
|
if(winMan_isMinimized()) exit;
|
||||||
|
|
||||||
#region tooltip
|
#region tooltip
|
||||||
if(is_struct(TOOLTIP)) {
|
if(!_MOUSE_BLOCK) {
|
||||||
if(struct_has(TOOLTIP, "drawTooltip"))
|
if(is_struct(TOOLTIP)) {
|
||||||
TOOLTIP.drawTooltip();
|
if(struct_has(TOOLTIP, "drawTooltip"))
|
||||||
|
TOOLTIP.drawTooltip();
|
||||||
} else if(is_array(TOOLTIP)) {
|
|
||||||
var content = TOOLTIP[0];
|
|
||||||
var type = TOOLTIP[1];
|
|
||||||
|
|
||||||
if(is_method(content)) content = content();
|
|
||||||
|
|
||||||
switch(type) {
|
|
||||||
case VALUE_TYPE.float :
|
|
||||||
case VALUE_TYPE.integer :
|
|
||||||
case VALUE_TYPE.text :
|
|
||||||
case VALUE_TYPE.struct :
|
|
||||||
case VALUE_TYPE.path :
|
|
||||||
draw_tooltip_text(string_real(content));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VALUE_TYPE.boolean :
|
} else if(is_array(TOOLTIP)) {
|
||||||
draw_tooltip_text(printBool(content));
|
var content = TOOLTIP[0];
|
||||||
break;
|
var type = TOOLTIP[1];
|
||||||
|
|
||||||
case VALUE_TYPE.curve :
|
if(is_method(content)) content = content();
|
||||||
draw_tooltip_text("[" + __txt("Curve Object") + "]");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VALUE_TYPE.color :
|
switch(type) {
|
||||||
draw_tooltip_color(content);
|
case VALUE_TYPE.float :
|
||||||
break;
|
case VALUE_TYPE.integer :
|
||||||
|
case VALUE_TYPE.text :
|
||||||
case VALUE_TYPE.gradient :
|
case VALUE_TYPE.struct :
|
||||||
draw_tooltip_gradient(content);
|
case VALUE_TYPE.path :
|
||||||
break;
|
draw_tooltip_text(string_real(content));
|
||||||
|
break;
|
||||||
case VALUE_TYPE.d3object :
|
|
||||||
draw_tooltip_text("[" + __txt("3D Object") + "]");
|
case VALUE_TYPE.boolean :
|
||||||
break;
|
draw_tooltip_text(printBool(content));
|
||||||
|
break;
|
||||||
case VALUE_TYPE.object :
|
|
||||||
draw_tooltip_text("[" + __txt("Object") + "]");
|
case VALUE_TYPE.curve :
|
||||||
break;
|
draw_tooltip_text("[" + __txt("Curve Object") + "]");
|
||||||
|
break;
|
||||||
case VALUE_TYPE.surface :
|
|
||||||
draw_tooltip_surface(content);
|
case VALUE_TYPE.color :
|
||||||
break;
|
draw_tooltip_color(content);
|
||||||
|
break;
|
||||||
case VALUE_TYPE.rigid :
|
|
||||||
draw_tooltip_text("[" + __txt("Rigidbody Object") + " (id: " + string(content[$ "object"]) + ")]");
|
case VALUE_TYPE.gradient :
|
||||||
break;
|
draw_tooltip_gradient(content);
|
||||||
|
break;
|
||||||
case VALUE_TYPE.particle :
|
|
||||||
var txt = "[" +
|
case VALUE_TYPE.d3object :
|
||||||
__txt("Particle Object") +
|
draw_tooltip_text("[" + __txt("3D Object") + "]");
|
||||||
" (size: " + string(array_length(content)) + ") " +
|
break;
|
||||||
"]";
|
|
||||||
draw_tooltip_text(txt);
|
case VALUE_TYPE.object :
|
||||||
break;
|
draw_tooltip_text("[" + __txt("Object") + "]");
|
||||||
|
break;
|
||||||
case VALUE_TYPE.pathnode :
|
|
||||||
draw_tooltip_text("[" + __txt("Path Object") + "]");
|
case VALUE_TYPE.surface :
|
||||||
break;
|
draw_tooltip_surface(content);
|
||||||
|
break;
|
||||||
case VALUE_TYPE.sdomain :
|
|
||||||
draw_tooltip_text("[" + __txt("Domain") + " (id: " + string(content) + ")]");
|
case VALUE_TYPE.rigid :
|
||||||
break;
|
draw_tooltip_text("[" + __txt("Rigidbody Object") + " (id: " + string(content[$ "object"]) + ")]");
|
||||||
|
break;
|
||||||
case VALUE_TYPE.strands :
|
|
||||||
var txt = __txt("Strands Object");
|
case VALUE_TYPE.particle :
|
||||||
if(is_struct(content))
|
var txt = "[" +
|
||||||
txt += " (strands: " + string(array_length(content.hairs)) + ")";
|
__txt("Particle Object") +
|
||||||
draw_tooltip_text("[" + txt + "]");
|
" (size: " + string(array_length(content)) + ") " +
|
||||||
break;
|
"]";
|
||||||
|
draw_tooltip_text(txt);
|
||||||
case VALUE_TYPE.mesh :
|
break;
|
||||||
var txt = __txt("Mesh Object");
|
|
||||||
if(is_struct(content))
|
case VALUE_TYPE.pathnode :
|
||||||
txt += " (triangles: " + string(array_length(content.triangles)) + ")";
|
draw_tooltip_text("[" + __txt("Path Object") + "]");
|
||||||
draw_tooltip_text("[" + txt + "]");
|
break;
|
||||||
break;
|
|
||||||
|
case VALUE_TYPE.sdomain :
|
||||||
case VALUE_TYPE.d3vertex :
|
draw_tooltip_text("[" + __txt("Domain") + " (id: " + string(content) + ")]");
|
||||||
var txt = __txt("3D Vertex");
|
break;
|
||||||
txt += " (groups: " + string(array_length(content)) + ")";
|
|
||||||
draw_tooltip_text("[" + txt + "]");
|
case VALUE_TYPE.strands :
|
||||||
break;
|
var txt = __txt("Strands Object");
|
||||||
|
if(is_struct(content))
|
||||||
case VALUE_TYPE.buffer :
|
txt += " (strands: " + string(array_length(content.hairs)) + ")";
|
||||||
draw_tooltip_buffer(content);
|
draw_tooltip_text("[" + txt + "]");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "sprite" :
|
case VALUE_TYPE.mesh :
|
||||||
draw_tooltip_sprite(content);
|
var txt = __txt("Mesh Object");
|
||||||
break;
|
if(is_struct(content))
|
||||||
|
txt += " (triangles: " + string(array_length(content.triangles)) + ")";
|
||||||
default :
|
draw_tooltip_text("[" + txt + "]");
|
||||||
var tt = "";
|
break;
|
||||||
if(is_struct(content)) tt = $"[{instanceof(content)}] {content}";
|
|
||||||
else tt = string(content);
|
case VALUE_TYPE.d3vertex :
|
||||||
|
var txt = __txt("3D Vertex");
|
||||||
draw_tooltip_text(tt);
|
txt += " (groups: " + string(array_length(content)) + ")";
|
||||||
}
|
draw_tooltip_text("[" + txt + "]");
|
||||||
} else if(TOOLTIP != "")
|
break;
|
||||||
draw_tooltip_text(TOOLTIP);
|
|
||||||
|
case VALUE_TYPE.buffer :
|
||||||
|
draw_tooltip_buffer(content);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "sprite" :
|
||||||
|
draw_tooltip_sprite(content);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
var tt = "";
|
||||||
|
if(is_struct(content)) tt = $"[{instanceof(content)}] {content}";
|
||||||
|
else tt = string(content);
|
||||||
|
|
||||||
|
draw_tooltip_text(tt);
|
||||||
|
}
|
||||||
|
} else if(TOOLTIP != "")
|
||||||
|
draw_tooltip_text(TOOLTIP);
|
||||||
|
}
|
||||||
TOOLTIP = "";
|
TOOLTIP = "";
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// 2024-04-21 15:26:33
|
// 2024-05-01 08:44:52
|
||||||
#event properties (no comments/etc. here are saved)
|
#event properties (no comments/etc. here are saved)
|
||||||
parent_index = -1;
|
parent_index = -1;
|
||||||
persistent = true;
|
persistent = true;
|
||||||
|
@ -1378,110 +1378,112 @@ if(APP_SURF_OVERRIDE) { #region
|
||||||
if(winMan_isMinimized()) exit;
|
if(winMan_isMinimized()) exit;
|
||||||
|
|
||||||
#region tooltip
|
#region tooltip
|
||||||
if(is_struct(TOOLTIP)) {
|
if(!_MOUSE_BLOCK) {
|
||||||
if(struct_has(TOOLTIP, "drawTooltip"))
|
if(is_struct(TOOLTIP)) {
|
||||||
TOOLTIP.drawTooltip();
|
if(struct_has(TOOLTIP, "drawTooltip"))
|
||||||
|
TOOLTIP.drawTooltip();
|
||||||
} else if(is_array(TOOLTIP)) {
|
|
||||||
var content = TOOLTIP[0];
|
|
||||||
var type = TOOLTIP[1];
|
|
||||||
|
|
||||||
if(is_method(content)) content = content();
|
|
||||||
|
|
||||||
switch(type) {
|
|
||||||
case VALUE_TYPE.float :
|
|
||||||
case VALUE_TYPE.integer :
|
|
||||||
case VALUE_TYPE.text :
|
|
||||||
case VALUE_TYPE.struct :
|
|
||||||
case VALUE_TYPE.path :
|
|
||||||
draw_tooltip_text(string_real(content));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VALUE_TYPE.boolean :
|
} else if(is_array(TOOLTIP)) {
|
||||||
draw_tooltip_text(printBool(content));
|
var content = TOOLTIP[0];
|
||||||
break;
|
var type = TOOLTIP[1];
|
||||||
|
|
||||||
case VALUE_TYPE.curve :
|
if(is_method(content)) content = content();
|
||||||
draw_tooltip_text("[" + __txt("Curve Object") + "]");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VALUE_TYPE.color :
|
switch(type) {
|
||||||
draw_tooltip_color(content);
|
case VALUE_TYPE.float :
|
||||||
break;
|
case VALUE_TYPE.integer :
|
||||||
|
case VALUE_TYPE.text :
|
||||||
case VALUE_TYPE.gradient :
|
case VALUE_TYPE.struct :
|
||||||
draw_tooltip_gradient(content);
|
case VALUE_TYPE.path :
|
||||||
break;
|
draw_tooltip_text(string_real(content));
|
||||||
|
break;
|
||||||
case VALUE_TYPE.d3object :
|
|
||||||
draw_tooltip_text("[" + __txt("3D Object") + "]");
|
case VALUE_TYPE.boolean :
|
||||||
break;
|
draw_tooltip_text(printBool(content));
|
||||||
|
break;
|
||||||
case VALUE_TYPE.object :
|
|
||||||
draw_tooltip_text("[" + __txt("Object") + "]");
|
case VALUE_TYPE.curve :
|
||||||
break;
|
draw_tooltip_text("[" + __txt("Curve Object") + "]");
|
||||||
|
break;
|
||||||
case VALUE_TYPE.surface :
|
|
||||||
draw_tooltip_surface(content);
|
case VALUE_TYPE.color :
|
||||||
break;
|
draw_tooltip_color(content);
|
||||||
|
break;
|
||||||
case VALUE_TYPE.rigid :
|
|
||||||
draw_tooltip_text("[" + __txt("Rigidbody Object") + " (id: " + string(content[$ "object"]) + ")]");
|
case VALUE_TYPE.gradient :
|
||||||
break;
|
draw_tooltip_gradient(content);
|
||||||
|
break;
|
||||||
case VALUE_TYPE.particle :
|
|
||||||
var txt = "[" +
|
case VALUE_TYPE.d3object :
|
||||||
__txt("Particle Object") +
|
draw_tooltip_text("[" + __txt("3D Object") + "]");
|
||||||
" (size: " + string(array_length(content)) + ") " +
|
break;
|
||||||
"]";
|
|
||||||
draw_tooltip_text(txt);
|
case VALUE_TYPE.object :
|
||||||
break;
|
draw_tooltip_text("[" + __txt("Object") + "]");
|
||||||
|
break;
|
||||||
case VALUE_TYPE.pathnode :
|
|
||||||
draw_tooltip_text("[" + __txt("Path Object") + "]");
|
case VALUE_TYPE.surface :
|
||||||
break;
|
draw_tooltip_surface(content);
|
||||||
|
break;
|
||||||
case VALUE_TYPE.sdomain :
|
|
||||||
draw_tooltip_text("[" + __txt("Domain") + " (id: " + string(content) + ")]");
|
case VALUE_TYPE.rigid :
|
||||||
break;
|
draw_tooltip_text("[" + __txt("Rigidbody Object") + " (id: " + string(content[$ "object"]) + ")]");
|
||||||
|
break;
|
||||||
case VALUE_TYPE.strands :
|
|
||||||
var txt = __txt("Strands Object");
|
case VALUE_TYPE.particle :
|
||||||
if(is_struct(content))
|
var txt = "[" +
|
||||||
txt += " (strands: " + string(array_length(content.hairs)) + ")";
|
__txt("Particle Object") +
|
||||||
draw_tooltip_text("[" + txt + "]");
|
" (size: " + string(array_length(content)) + ") " +
|
||||||
break;
|
"]";
|
||||||
|
draw_tooltip_text(txt);
|
||||||
case VALUE_TYPE.mesh :
|
break;
|
||||||
var txt = __txt("Mesh Object");
|
|
||||||
if(is_struct(content))
|
case VALUE_TYPE.pathnode :
|
||||||
txt += " (triangles: " + string(array_length(content.triangles)) + ")";
|
draw_tooltip_text("[" + __txt("Path Object") + "]");
|
||||||
draw_tooltip_text("[" + txt + "]");
|
break;
|
||||||
break;
|
|
||||||
|
case VALUE_TYPE.sdomain :
|
||||||
case VALUE_TYPE.d3vertex :
|
draw_tooltip_text("[" + __txt("Domain") + " (id: " + string(content) + ")]");
|
||||||
var txt = __txt("3D Vertex");
|
break;
|
||||||
txt += " (groups: " + string(array_length(content)) + ")";
|
|
||||||
draw_tooltip_text("[" + txt + "]");
|
case VALUE_TYPE.strands :
|
||||||
break;
|
var txt = __txt("Strands Object");
|
||||||
|
if(is_struct(content))
|
||||||
case VALUE_TYPE.buffer :
|
txt += " (strands: " + string(array_length(content.hairs)) + ")";
|
||||||
draw_tooltip_buffer(content);
|
draw_tooltip_text("[" + txt + "]");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "sprite" :
|
case VALUE_TYPE.mesh :
|
||||||
draw_tooltip_sprite(content);
|
var txt = __txt("Mesh Object");
|
||||||
break;
|
if(is_struct(content))
|
||||||
|
txt += " (triangles: " + string(array_length(content.triangles)) + ")";
|
||||||
default :
|
draw_tooltip_text("[" + txt + "]");
|
||||||
var tt = "";
|
break;
|
||||||
if(is_struct(content)) tt = $"[{instanceof(content)}] {content}";
|
|
||||||
else tt = string(content);
|
case VALUE_TYPE.d3vertex :
|
||||||
|
var txt = __txt("3D Vertex");
|
||||||
draw_tooltip_text(tt);
|
txt += " (groups: " + string(array_length(content)) + ")";
|
||||||
}
|
draw_tooltip_text("[" + txt + "]");
|
||||||
} else if(TOOLTIP != "")
|
break;
|
||||||
draw_tooltip_text(TOOLTIP);
|
|
||||||
|
case VALUE_TYPE.buffer :
|
||||||
|
draw_tooltip_buffer(content);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "sprite" :
|
||||||
|
draw_tooltip_sprite(content);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
var tt = "";
|
||||||
|
if(is_struct(content)) tt = $"[{instanceof(content)}] {content}";
|
||||||
|
else tt = string(content);
|
||||||
|
|
||||||
|
draw_tooltip_text(tt);
|
||||||
|
}
|
||||||
|
} else if(TOOLTIP != "")
|
||||||
|
draw_tooltip_text(TOOLTIP);
|
||||||
|
}
|
||||||
TOOLTIP = "";
|
TOOLTIP = "";
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
670
#backups/scripts/BBMOD_Quaternion/BBMOD_Quaternion.gml.backup0
Normal file
670
#backups/scripts/BBMOD_Quaternion/BBMOD_Quaternion.gml.backup0
Normal file
|
@ -0,0 +1,670 @@
|
||||||
|
// 2024-05-01 17:17:25
|
||||||
|
// feather ignore all
|
||||||
|
|
||||||
|
/// @func BBMOD_Quaternion([_x, _y, _z, _w])
|
||||||
|
///
|
||||||
|
/// @desc A quaternion.
|
||||||
|
///
|
||||||
|
/// @param {Real} [_x] The first component of the quaternion. Defaults to 0.
|
||||||
|
/// @param {Real} [_y] The second component of the quaternion. Defaults to 0.
|
||||||
|
/// @param {Real} [_z] The third component of the quaternion. Defaults to 0.
|
||||||
|
/// @param {Real} [_w] The fourth component of the quaternion. Defaults to 1.
|
||||||
|
///
|
||||||
|
/// @note If you leave the arguments to their default values, then an identity
|
||||||
|
/// quaternion is created.
|
||||||
|
function BBMOD_Quaternion(_x=0.0, _y=0.0, _z=0.0, _w=1.0) constructor
|
||||||
|
{
|
||||||
|
/// @var {Real} The first component of the quaternion.
|
||||||
|
X = _x;
|
||||||
|
|
||||||
|
/// @var {Real} The second component of the quaternion.
|
||||||
|
Y = _y;
|
||||||
|
|
||||||
|
/// @var {Real} The third component of the quaternion.
|
||||||
|
Z = _z;
|
||||||
|
|
||||||
|
/// @var {Real} The fourth component of the quaternion.
|
||||||
|
W = _w;
|
||||||
|
|
||||||
|
static set = function(x, y, z, w) {
|
||||||
|
INLINE
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
Z = z;
|
||||||
|
W = w;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @func Add(_q)
|
||||||
|
///
|
||||||
|
/// @desc Adds quaternions and returns the result as a new quaternion.
|
||||||
|
///
|
||||||
|
/// @param {Struct.BBMOD_Quaternion} _q The other quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Add = function (_q) {
|
||||||
|
INLINE
|
||||||
|
return new BBMOD_Quaternion(
|
||||||
|
X + _q.X,
|
||||||
|
Y + _q.Y,
|
||||||
|
Z + _q.Z,
|
||||||
|
W + _q.W
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Clone()
|
||||||
|
///
|
||||||
|
/// @desc Creates a clone of the quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Clone = function () {
|
||||||
|
INLINE
|
||||||
|
return new BBMOD_Quaternion(X, Y, Z, W);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Conjugate()
|
||||||
|
///
|
||||||
|
/// @desc Conjugates the quaternion and returns the result as a quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Conjugate = function () {
|
||||||
|
INLINE
|
||||||
|
return new BBMOD_Quaternion(-X, -Y, -Z, W);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Copy(_dest)
|
||||||
|
///
|
||||||
|
/// @desc Copies components of the quaternion into other quaternion.
|
||||||
|
///
|
||||||
|
/// @param {Struct.BBMOD_Quaternion} _dest The destination quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} Returns `self`.
|
||||||
|
static Copy = function (_dest) {
|
||||||
|
INLINE
|
||||||
|
_dest.X = X;
|
||||||
|
_dest.Y = Y;
|
||||||
|
_dest.Z = Z;
|
||||||
|
_dest.W = W;
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Dot(_q)
|
||||||
|
///
|
||||||
|
/// @desc Computes a dot product of two dual quaternions.
|
||||||
|
///
|
||||||
|
/// @param {Struct.BBMOD_Quaternion} _q The other quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Real} The dot product of the quaternions.
|
||||||
|
static Dot = function (_q) {
|
||||||
|
INLINE
|
||||||
|
return (
|
||||||
|
X * _q.X
|
||||||
|
+ Y * _q.Y
|
||||||
|
+ Z * _q.Z
|
||||||
|
+ W * _q.W
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Exp()
|
||||||
|
///
|
||||||
|
/// @desc Computes an exponential map of the quaternion and returns
|
||||||
|
/// the result as a new quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Exp = function () {
|
||||||
|
INLINE
|
||||||
|
var _length = Length();
|
||||||
|
if (_length >= math_get_epsilon())
|
||||||
|
{
|
||||||
|
var _sinc = Sinc(_length);
|
||||||
|
return new BBMOD_Quaternion(
|
||||||
|
X * _sinc,
|
||||||
|
Y * _sinc,
|
||||||
|
Z * _sinc,
|
||||||
|
exp(W) * cos(_length)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return new BBMOD_Quaternion(0.0, 0.0, 0.0, exp(W));
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func FromArray(_array[, _index])
|
||||||
|
///
|
||||||
|
/// @desc Loads quaternion components `(x, y, z, w)` from an array.
|
||||||
|
///
|
||||||
|
/// @param {Array<Real>} _array The array to read the quaternion components
|
||||||
|
/// from.
|
||||||
|
/// @param {Real} [_index] The index to start reading the quaternion
|
||||||
|
/// components from. Defaults to 0.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} Returns `self`.
|
||||||
|
static FromArray = function (_array, _index=0) {
|
||||||
|
INLINE
|
||||||
|
X = _array[_index];
|
||||||
|
Y = _array[_index + 1];
|
||||||
|
Z = _array[_index + 2];
|
||||||
|
W = _array[_index + 3];
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func FromAxisAngle(_axis, _angle)
|
||||||
|
///
|
||||||
|
/// @desc Initializes the quaternion using an axis and an angle.
|
||||||
|
///
|
||||||
|
/// @param {Struct.BBMOD_Vec3} _axis The axis of rotaiton.
|
||||||
|
///
|
||||||
|
/// @param {Real} _angle The rotation angle.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} Returns `self`.
|
||||||
|
static FromAxisAngle = function (_axis, _angle) {
|
||||||
|
INLINE
|
||||||
|
_angle = -_angle;
|
||||||
|
var _sinHalfAngle = dsin(_angle * 0.5);
|
||||||
|
X = is_nan(_axis.X)? 0 : _axis.X * _sinHalfAngle;
|
||||||
|
Y = is_nan(_axis.Y)? 0 : _axis.Y * _sinHalfAngle;
|
||||||
|
Z = is_nan(_axis.Z)? 0 : _axis.Z * _sinHalfAngle;
|
||||||
|
W = dcos(_angle * 0.5);
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func FromBuffer(_buffer, _type)
|
||||||
|
///
|
||||||
|
/// @desc Loads quaternion components `(x, y, z, w)` from a buffer.
|
||||||
|
///
|
||||||
|
/// @param {Id.Buffer} _buffer The buffer to read the quaternion components
|
||||||
|
/// from.
|
||||||
|
///
|
||||||
|
/// @param {Constant.BufferDataType} [_type] The type of each component.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} Returns `self`.
|
||||||
|
static FromBuffer = function (_buffer, _type) {
|
||||||
|
INLINE
|
||||||
|
X = buffer_read(_buffer, _type);
|
||||||
|
Y = buffer_read(_buffer, _type);
|
||||||
|
Z = buffer_read(_buffer, _type);
|
||||||
|
W = buffer_read(_buffer, _type);
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func FromEuler(_x, _y, _z)
|
||||||
|
///
|
||||||
|
/// @desc Initializes the quaternion using euler angles.
|
||||||
|
///
|
||||||
|
/// @param {Real} _x The rotation around the X axis (in degrees).
|
||||||
|
/// @param {Real} _y The rotation around the Y axis (in degrees).
|
||||||
|
/// @param {Real} _z The rotation around the Z axis (in degrees).
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} Returns `self`.
|
||||||
|
///
|
||||||
|
/// @note The order of rotations is YXZ, same as in the `matrix_build`
|
||||||
|
/// function.
|
||||||
|
static FromEuler = function (_x, _y, _z) {
|
||||||
|
INLINE
|
||||||
|
|
||||||
|
_x = -_x * 0.5;
|
||||||
|
_y = -_y * 0.5;
|
||||||
|
_z = -_z * 0.5;
|
||||||
|
|
||||||
|
var _q1Sin, _q1Cos, _temp;
|
||||||
|
var _qX, _qY, _qZ, _qW;
|
||||||
|
|
||||||
|
_q1Sin = dsin(_z);
|
||||||
|
_q1Cos = dcos(_z);
|
||||||
|
|
||||||
|
_temp = dsin(_x);
|
||||||
|
|
||||||
|
_qX = _q1Cos * _temp;
|
||||||
|
_qY = _q1Sin * _temp;
|
||||||
|
|
||||||
|
_temp = dcos(_x);
|
||||||
|
|
||||||
|
_qZ = _q1Sin * _temp;
|
||||||
|
_qW = _q1Cos * _temp;
|
||||||
|
|
||||||
|
_q1Sin = dsin(_y);
|
||||||
|
_q1Cos = dcos(_y);
|
||||||
|
|
||||||
|
X = _qX * _q1Cos - _qZ * _q1Sin;
|
||||||
|
Y = _qW * _q1Sin + _qY * _q1Cos;
|
||||||
|
Z = _qZ * _q1Cos + _qX * _q1Sin;
|
||||||
|
W = _qW * _q1Cos - _qY * _q1Sin;
|
||||||
|
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func FromLookRotation(_forward, _up)
|
||||||
|
///
|
||||||
|
/// @desc Initializes the quaternion using a forward and an up vector. These
|
||||||
|
/// vectors must not be parallel! If they are, the quaternion will be set to an
|
||||||
|
/// identity.
|
||||||
|
///
|
||||||
|
/// @param {Struct.BBMOD_Vec3} _forward The vector facing forward.
|
||||||
|
/// @param {Struct.BBMOD_Vec3} _up The vector facing up.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} Returns `self`.
|
||||||
|
static FromLookRotation = function (_forward, _up) {
|
||||||
|
INLINE
|
||||||
|
|
||||||
|
_forward = new BBMOD_Vec3(_forward);
|
||||||
|
_up = new BBMOD_Vec3(_up);
|
||||||
|
|
||||||
|
if (!_forward.Orthonormalize(_up)) {
|
||||||
|
X = 0.0;
|
||||||
|
Y = 0.0;
|
||||||
|
Z = 0.0;
|
||||||
|
W = 1.0;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _right = _up.Cross(_forward);
|
||||||
|
var _w = sqrt(abs(1.0 + _right.X + _up.Y + _forward.Z)) * 0.5;
|
||||||
|
var _w4Recip = _w == 0? 0 : 1.0 / (4.0 * _w);
|
||||||
|
|
||||||
|
X = (_up.Z - _forward.Y) * _w4Recip;
|
||||||
|
Y = (_forward.X - _right.Z) * _w4Recip;
|
||||||
|
Z = (_right.Y - _up.X) * _w4Recip;
|
||||||
|
W = _w;
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
|
||||||
|
static FromMatrix = function(rotMatrix) {
|
||||||
|
INLINE
|
||||||
|
|
||||||
|
W = sqrt(1 + rotMatrix[0] + rotMatrix[5] + rotMatrix[10]) / 2;
|
||||||
|
X = (rotMatrix[9] - rotMatrix[6]) / (4 * W);
|
||||||
|
Y = (rotMatrix[2] - rotMatrix[8]) / (4 * W);
|
||||||
|
Z = (rotMatrix[4] - rotMatrix[1]) / (4 * W);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @func GetAngle()
|
||||||
|
///
|
||||||
|
/// @desc Retrieves the rotation angle of the quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Real} The rotation angle.
|
||||||
|
static GetAngle = function () {
|
||||||
|
INLINE
|
||||||
|
return radtodeg(arccos(W) * 2.0);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func GetAxis()
|
||||||
|
///
|
||||||
|
/// @desc Retrieves the axis of rotation of the quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Vec3} The axis of rotation.
|
||||||
|
static GetAxis = function () {
|
||||||
|
INLINE
|
||||||
|
var _sinThetaInv = 1.0 / sin(arccos(W));
|
||||||
|
return new BBMOD_Vec3(
|
||||||
|
X * _sinThetaInv,
|
||||||
|
Y * _sinThetaInv,
|
||||||
|
Z * _sinThetaInv
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Inverse()
|
||||||
|
///
|
||||||
|
/// @desc Computes an inverse of the quaternion and returns the result
|
||||||
|
/// as a new quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Inverse = function () {
|
||||||
|
INLINE
|
||||||
|
return Length() == 0? new BBMOD_Quaternion() : Conjugate().Scale(1.0 / Length());
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Length()
|
||||||
|
///
|
||||||
|
/// @desc Computes the length of the quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Real} The length of the quaternion.
|
||||||
|
static Length = function () {
|
||||||
|
INLINE
|
||||||
|
return sqrt(
|
||||||
|
X * X
|
||||||
|
+ Y * Y
|
||||||
|
+ Z * Z
|
||||||
|
+ W * W
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func LengthSqr()
|
||||||
|
///
|
||||||
|
/// @desc Computes a squared length of the quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Real} The squared length of the quaternion.
|
||||||
|
static LengthSqr = function () {
|
||||||
|
INLINE
|
||||||
|
return (
|
||||||
|
X * X
|
||||||
|
+ Y * Y
|
||||||
|
+ Z * Z
|
||||||
|
+ W * W
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Lerp(_q, _s)
|
||||||
|
///
|
||||||
|
/// @desc Computes a linear interpolation of two quaternions
|
||||||
|
/// and returns the result as a new quaternion.
|
||||||
|
///
|
||||||
|
/// @param {Struct.BBMOD_Quaternion} _q The other quaternion.
|
||||||
|
/// @param {Real} _s The interpolation factor.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Lerp = function (_q, _s) {
|
||||||
|
INLINE
|
||||||
|
return new BBMOD_Quaternion(
|
||||||
|
lerp(X, _q.X, _s),
|
||||||
|
lerp(Y, _q.Y, _s),
|
||||||
|
lerp(Z, _q.Z, _s),
|
||||||
|
lerp(W, _q.W, _s)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Log()
|
||||||
|
///
|
||||||
|
/// @desc Computes the logarithm map of the quaternion and returns the
|
||||||
|
/// result as a new quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Log = function () {
|
||||||
|
INLINE
|
||||||
|
var _length = Length();
|
||||||
|
var _w = logn(2.71828, _length);
|
||||||
|
var _a = arccos(W / _length);
|
||||||
|
if (_a >= math_get_epsilon())
|
||||||
|
{
|
||||||
|
var _mag = 1.0 / _length / Sinc(_a);
|
||||||
|
return new BBMOD_Quaternion(
|
||||||
|
X * _mag,
|
||||||
|
Y * _mag,
|
||||||
|
Z * _mag,
|
||||||
|
_w
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return new BBMOD_Quaternion(0.0, 0.0, 0.0, _w);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Mul(_q)
|
||||||
|
///
|
||||||
|
/// @desc Multiplies two quaternions and returns the result as a new
|
||||||
|
/// quaternion.
|
||||||
|
///
|
||||||
|
/// @param {Struct.BBMOD_Quaternion} _q The other quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Mul = function (_q) {
|
||||||
|
INLINE
|
||||||
|
return new BBMOD_Quaternion(
|
||||||
|
W * _q.X + X * _q.W + Y * _q.Z - Z * _q.Y,
|
||||||
|
W * _q.Y + Y * _q.W + Z * _q.X - X * _q.Z,
|
||||||
|
W * _q.Z + Z * _q.W + X * _q.Y - Y * _q.X,
|
||||||
|
W * _q.W - X * _q.X - Y * _q.Y - Z * _q.Z
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Normalize()
|
||||||
|
///
|
||||||
|
/// @desc Normalizes the quaternion and returns the result as a new
|
||||||
|
/// quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Normalize = function () {
|
||||||
|
INLINE
|
||||||
|
var _lengthSqr = LengthSqr();
|
||||||
|
|
||||||
|
if(_lengthSqr == 0)
|
||||||
|
return new BBMOD_Quaternion();
|
||||||
|
|
||||||
|
if (_lengthSqr >= math_get_epsilon())
|
||||||
|
return Scale(1.0 / sqrt(_lengthSqr));
|
||||||
|
return Clone();
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Rotate(_v)
|
||||||
|
///
|
||||||
|
/// @desc Rotates a vector using the quaternion and returns the result
|
||||||
|
/// as a new vector.
|
||||||
|
///
|
||||||
|
/// @param {Struct.BBMOD_Vec3} _v The vector to rotate.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Vec3} The created vector.
|
||||||
|
static Rotate = function (_v) {
|
||||||
|
INLINE
|
||||||
|
|
||||||
|
var _tovec = is_instanceof(_v, __vec3);
|
||||||
|
if(_tovec) _v = new BBMOD_Vec3(_v.x, _v.y, _v.z);
|
||||||
|
|
||||||
|
var _q = Normalize();
|
||||||
|
var _V = new BBMOD_Quaternion(_v.X, _v.Y, _v.Z, 0.0);
|
||||||
|
var _rot = _q.Mul(_V).Mul(_q.Conjugate());
|
||||||
|
|
||||||
|
var res;
|
||||||
|
if(_tovec) res = new __vec3(_rot.X, _rot.Y, _rot.Z);
|
||||||
|
else res = new BBMOD_Vec3(_rot.X, _rot.Y, _rot.Z);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Scale(_s)
|
||||||
|
///
|
||||||
|
/// @desc Scales each component of the quaternion by a real value and
|
||||||
|
/// returns the result as a new quaternion.
|
||||||
|
///
|
||||||
|
/// @param {Real} _s The value to scale the quaternion by.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Scale = function (_s) {
|
||||||
|
INLINE
|
||||||
|
return new BBMOD_Quaternion(
|
||||||
|
X * _s,
|
||||||
|
Y * _s,
|
||||||
|
Z * _s,
|
||||||
|
W * _s
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
static Sinc = function (_x) {
|
||||||
|
INLINE
|
||||||
|
return (_x >= math_get_epsilon()) ? (sin(_x) / _x) : 1.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Slerp(_q, _s)
|
||||||
|
///
|
||||||
|
/// @desc Computes a spherical linear interpolation of two quaternions
|
||||||
|
/// and returns the result as a new quaternion.
|
||||||
|
///
|
||||||
|
/// @param {Struct.BBMOD_Quaternion} _q The other quaternion.
|
||||||
|
/// @param {Real} _s The interpolation factor.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Slerp = function (_q, _s) {
|
||||||
|
INLINE
|
||||||
|
|
||||||
|
var _q10 = X;
|
||||||
|
var _q11 = Y;
|
||||||
|
var _q12 = Z;
|
||||||
|
var _q13 = W;
|
||||||
|
|
||||||
|
var _q20 = _q.X;
|
||||||
|
var _q21 = _q.Y;
|
||||||
|
var _q22 = _q.Z;
|
||||||
|
var _q23 = _q.W;
|
||||||
|
|
||||||
|
var _norm;
|
||||||
|
|
||||||
|
_norm = 1.0 / sqrt(_q10 * _q10
|
||||||
|
+ _q11 * _q11
|
||||||
|
+ _q12 * _q12
|
||||||
|
+ _q13 * _q13);
|
||||||
|
|
||||||
|
_q10 *= _norm;
|
||||||
|
_q11 *= _norm;
|
||||||
|
_q12 *= _norm;
|
||||||
|
_q13 *= _norm;
|
||||||
|
|
||||||
|
_norm = sqrt(_q20 * _q20
|
||||||
|
+ _q21 * _q21
|
||||||
|
+ _q22 * _q22
|
||||||
|
+ _q23 * _q23);
|
||||||
|
|
||||||
|
_q20 *= _norm;
|
||||||
|
_q21 *= _norm;
|
||||||
|
_q22 *= _norm;
|
||||||
|
_q23 *= _norm;
|
||||||
|
|
||||||
|
var _dot = _q10 * _q20
|
||||||
|
+ _q11 * _q21
|
||||||
|
+ _q12 * _q22
|
||||||
|
+ _q13 * _q23;
|
||||||
|
|
||||||
|
if (_dot < 0.0)
|
||||||
|
{
|
||||||
|
_dot = -_dot;
|
||||||
|
_q20 *= -1.0;
|
||||||
|
_q21 *= -1.0;
|
||||||
|
_q22 *= -1.0;
|
||||||
|
_q23 *= -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_dot > 0.9995)
|
||||||
|
{
|
||||||
|
return new BBMOD_Quaternion(
|
||||||
|
lerp(_q10, _q20, _s),
|
||||||
|
lerp(_q11, _q21, _s),
|
||||||
|
lerp(_q12, _q22, _s),
|
||||||
|
lerp(_q13, _q23, _s)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var _theta0 = arccos(_dot);
|
||||||
|
var _theta = _theta0 * _s;
|
||||||
|
var _sinTheta = sin(_theta);
|
||||||
|
var _sinTheta0 = sin(_theta0);
|
||||||
|
var _s2 = _sinTheta / _sinTheta0;
|
||||||
|
var _s1 = cos(_theta) - (_dot * _s2);
|
||||||
|
|
||||||
|
return new BBMOD_Quaternion(
|
||||||
|
(_q10 * _s1) + (_q20 * _s2),
|
||||||
|
(_q11 * _s1) + (_q21 * _s2),
|
||||||
|
(_q12 * _s1) + (_q22 * _s2),
|
||||||
|
(_q13 * _s1) + (_q23 * _s2)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func ToArray([_array[, _index]])
|
||||||
|
///
|
||||||
|
/// @desc Writes components `(x, y, z, w)` of the quaternion into an array.
|
||||||
|
///
|
||||||
|
/// @param {Array<Real>} [_array] The destination array. If not defined, a
|
||||||
|
/// new one is created.
|
||||||
|
/// @param {Real} [_index] The index to start writing to. Defaults to 0.
|
||||||
|
///
|
||||||
|
/// @return {Array<Real>} Returns the destination array.
|
||||||
|
static ToArray = function (_array=undefined, _index=0) {
|
||||||
|
INLINE
|
||||||
|
_array ??= array_create(4, 0.0);
|
||||||
|
_array[@ _index] = X;
|
||||||
|
_array[@ _index + 1] = Y;
|
||||||
|
_array[@ _index + 2] = Z;
|
||||||
|
_array[@ _index + 3] = W;
|
||||||
|
return _array;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func ToBuffer(_buffer, _type)
|
||||||
|
///
|
||||||
|
/// @desc Writes the quaternion into a buffer.
|
||||||
|
///
|
||||||
|
/// @param {Id.Buffer} _buffer The buffer to write the quaternion to.
|
||||||
|
/// @param {Constant.BufferDataType} _type The type of each component.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} Returns `self`.
|
||||||
|
static ToBuffer = function (_buffer, _type) {
|
||||||
|
INLINE
|
||||||
|
buffer_write(_buffer, _type, X);
|
||||||
|
buffer_write(_buffer, _type, Y);
|
||||||
|
buffer_write(_buffer, _type, Z);
|
||||||
|
buffer_write(_buffer, _type, W);
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
|
||||||
|
static ToEuler = function(isArray = false) {
|
||||||
|
var ysqr = Y * Y;
|
||||||
|
|
||||||
|
// roll (x-axis rotation)
|
||||||
|
var t0 = +2.0 * (W * X + Y * Z);
|
||||||
|
var t1 = +1.0 - 2.0 * (X * X + ysqr);
|
||||||
|
var roll = arctan2(t0, t1);
|
||||||
|
|
||||||
|
// pitch (y-axis rotation)
|
||||||
|
var t2 = +2.0 * (W * Y - Z * X);
|
||||||
|
t2 = clamp(t2, -1.0, 1.0); // Prevent numerical instability
|
||||||
|
var pitch = arcsin(t2);
|
||||||
|
|
||||||
|
// yaw (z-axis rotation)
|
||||||
|
var t3 = +2.0 * (W * Z + X * Y);
|
||||||
|
var t4 = +1.0 - 2.0 * (ysqr + Z * Z);
|
||||||
|
var yaw = arctan2(t3, t4);
|
||||||
|
|
||||||
|
// Convert radians to degrees
|
||||||
|
var _dx = roll * 180.0 / pi;
|
||||||
|
var _dy = pitch * 180.0 / pi;
|
||||||
|
var _dz = yaw * 180.0 / pi;
|
||||||
|
|
||||||
|
_dx = round(_dx * 1000) / 1000;
|
||||||
|
_dy = round(_dy * 1000) / 1000;
|
||||||
|
_dz = round(_dz * 1000) / 1000;
|
||||||
|
|
||||||
|
return isArray? [ _dx, _dy, _dz ] : new __rot3(_dx, _dy, _dz);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @func ToMatrix([_dest[, _index]])
|
||||||
|
///
|
||||||
|
/// @desc Converts quaternion into a matrix.
|
||||||
|
///
|
||||||
|
/// @param {Array<Real>} [_dest] The destination array. If not specified, a
|
||||||
|
/// new one is created.
|
||||||
|
/// @param {Real} [_index] The starting index in the destination array.
|
||||||
|
/// Defaults to 0.
|
||||||
|
///
|
||||||
|
/// @return {Array<Real>} Returns the destination array.
|
||||||
|
static ToMatrix = function (_dest=undefined, _index=0) {
|
||||||
|
INLINE
|
||||||
|
|
||||||
|
_dest ??= matrix_build_identity();
|
||||||
|
|
||||||
|
if(is_nan(X)) return _dest;
|
||||||
|
|
||||||
|
var _norm = Normalize();
|
||||||
|
|
||||||
|
var _temp0, _temp1, _temp2;
|
||||||
|
var _q0 = _norm.X;
|
||||||
|
var _q1 = _norm.Y;
|
||||||
|
var _q2 = _norm.Z;
|
||||||
|
var _q3 = _norm.W;
|
||||||
|
|
||||||
|
_temp0 = _q0 * _q0;
|
||||||
|
_temp1 = _q1 * _q1;
|
||||||
|
_temp2 = _q2 * _q2;
|
||||||
|
_dest[@ _index] = 1.0 - 2.0 * (_temp1 + _temp2);
|
||||||
|
_dest[@ _index + 5] = 1.0 - 2.0 * (_temp0 + _temp2);
|
||||||
|
_dest[@ _index + 10] = 1.0 - 2.0 * (_temp0 + _temp1);
|
||||||
|
|
||||||
|
_temp0 = _q0 * _q1;
|
||||||
|
_temp1 = _q3 * _q2;
|
||||||
|
_dest[@ _index + 1] = 2.0 * (_temp0 + _temp1);
|
||||||
|
_dest[@ _index + 4] = 2.0 * (_temp0 - _temp1);
|
||||||
|
|
||||||
|
_temp0 = _q0 * _q2
|
||||||
|
_temp1 = _q3 * _q1;
|
||||||
|
_dest[@ _index + 2] = 2.0 * (_temp0 - _temp1);
|
||||||
|
_dest[@ _index + 8] = 2.0 * (_temp0 + _temp1);
|
||||||
|
|
||||||
|
_temp0 = _q1 * _q2;
|
||||||
|
_temp1 = _q3 * _q0;
|
||||||
|
_dest[@ _index + 6] = 2.0 * (_temp0 + _temp1);
|
||||||
|
_dest[@ _index + 9] = 2.0 * (_temp0 - _temp1);
|
||||||
|
|
||||||
|
return _dest;
|
||||||
|
};
|
||||||
|
}
|
670
#backups/scripts/BBMOD_Quaternion/BBMOD_Quaternion.gml.backup1
Normal file
670
#backups/scripts/BBMOD_Quaternion/BBMOD_Quaternion.gml.backup1
Normal file
|
@ -0,0 +1,670 @@
|
||||||
|
// 2024-05-01 17:17:23
|
||||||
|
// feather ignore all
|
||||||
|
|
||||||
|
/// @func BBMOD_Quaternion([_x, _y, _z, _w])
|
||||||
|
///
|
||||||
|
/// @desc A quaternion.
|
||||||
|
///
|
||||||
|
/// @param {Real} [_x] The first component of the quaternion. Defaults to 0.
|
||||||
|
/// @param {Real} [_y] The second component of the quaternion. Defaults to 0.
|
||||||
|
/// @param {Real} [_z] The third component of the quaternion. Defaults to 0.
|
||||||
|
/// @param {Real} [_w] The fourth component of the quaternion. Defaults to 1.
|
||||||
|
///
|
||||||
|
/// @note If you leave the arguments to their default values, then an identity
|
||||||
|
/// quaternion is created.
|
||||||
|
function BBMOD_Quaternion(_x=0.0, _y=0.0, _z=0.0, _w=1.0) constructor
|
||||||
|
{
|
||||||
|
/// @var {Real} The first component of the quaternion.
|
||||||
|
X = _x;
|
||||||
|
|
||||||
|
/// @var {Real} The second component of the quaternion.
|
||||||
|
Y = _y;
|
||||||
|
|
||||||
|
/// @var {Real} The third component of the quaternion.
|
||||||
|
Z = _z;
|
||||||
|
|
||||||
|
/// @var {Real} The fourth component of the quaternion.
|
||||||
|
W = _w;
|
||||||
|
|
||||||
|
static set = function(x, y, z, w) {
|
||||||
|
INLINE
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
Z = z;
|
||||||
|
W = w;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @func Add(_q)
|
||||||
|
///
|
||||||
|
/// @desc Adds quaternions and returns the result as a new quaternion.
|
||||||
|
///
|
||||||
|
/// @param {Struct.BBMOD_Quaternion} _q The other quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Add = function (_q) {
|
||||||
|
INLINE
|
||||||
|
return new BBMOD_Quaternion(
|
||||||
|
X + _q.X,
|
||||||
|
Y + _q.Y,
|
||||||
|
Z + _q.Z,
|
||||||
|
W + _q.W
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Clone()
|
||||||
|
///
|
||||||
|
/// @desc Creates a clone of the quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Clone = function () {
|
||||||
|
INLINE
|
||||||
|
return new BBMOD_Quaternion(X, Y, Z, W);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Conjugate()
|
||||||
|
///
|
||||||
|
/// @desc Conjugates the quaternion and returns the result as a quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Conjugate = function () {
|
||||||
|
INLINE
|
||||||
|
return new BBMOD_Quaternion(-X, -Y, -Z, W);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Copy(_dest)
|
||||||
|
///
|
||||||
|
/// @desc Copies components of the quaternion into other quaternion.
|
||||||
|
///
|
||||||
|
/// @param {Struct.BBMOD_Quaternion} _dest The destination quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} Returns `self`.
|
||||||
|
static Copy = function (_dest) {
|
||||||
|
INLINE
|
||||||
|
_dest.X = X;
|
||||||
|
_dest.Y = Y;
|
||||||
|
_dest.Z = Z;
|
||||||
|
_dest.W = W;
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Dot(_q)
|
||||||
|
///
|
||||||
|
/// @desc Computes a dot product of two dual quaternions.
|
||||||
|
///
|
||||||
|
/// @param {Struct.BBMOD_Quaternion} _q The other quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Real} The dot product of the quaternions.
|
||||||
|
static Dot = function (_q) {
|
||||||
|
INLINE
|
||||||
|
return (
|
||||||
|
X * _q.X
|
||||||
|
+ Y * _q.Y
|
||||||
|
+ Z * _q.Z
|
||||||
|
+ W * _q.W
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Exp()
|
||||||
|
///
|
||||||
|
/// @desc Computes an exponential map of the quaternion and returns
|
||||||
|
/// the result as a new quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Exp = function () {
|
||||||
|
INLINE
|
||||||
|
var _length = Length();
|
||||||
|
if (_length >= math_get_epsilon())
|
||||||
|
{
|
||||||
|
var _sinc = Sinc(_length);
|
||||||
|
return new BBMOD_Quaternion(
|
||||||
|
X * _sinc,
|
||||||
|
Y * _sinc,
|
||||||
|
Z * _sinc,
|
||||||
|
exp(W) * cos(_length)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return new BBMOD_Quaternion(0.0, 0.0, 0.0, exp(W));
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func FromArray(_array[, _index])
|
||||||
|
///
|
||||||
|
/// @desc Loads quaternion components `(x, y, z, w)` from an array.
|
||||||
|
///
|
||||||
|
/// @param {Array<Real>} _array The array to read the quaternion components
|
||||||
|
/// from.
|
||||||
|
/// @param {Real} [_index] The index to start reading the quaternion
|
||||||
|
/// components from. Defaults to 0.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} Returns `self`.
|
||||||
|
static FromArray = function (_array, _index=0) {
|
||||||
|
INLINE
|
||||||
|
X = _array[_index];
|
||||||
|
Y = _array[_index + 1];
|
||||||
|
Z = _array[_index + 2];
|
||||||
|
W = _array[_index + 3];
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func FromAxisAngle(_axis, _angle)
|
||||||
|
///
|
||||||
|
/// @desc Initializes the quaternion using an axis and an angle.
|
||||||
|
///
|
||||||
|
/// @param {Struct.BBMOD_Vec3} _axis The axis of rotaiton.
|
||||||
|
///
|
||||||
|
/// @param {Real} _angle The rotation angle.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} Returns `self`.
|
||||||
|
static FromAxisAngle = function (_axis, _angle) {
|
||||||
|
INLINE
|
||||||
|
_angle = -_angle;
|
||||||
|
var _sinHalfAngle = dsin(_angle * 0.5);
|
||||||
|
X = is_nan(_axis.X)? 0 : _axis.X * _sinHalfAngle;
|
||||||
|
Y = is_nan(_axis.Y)? 0 : _axis.Y * _sinHalfAngle;
|
||||||
|
Z = is_nan(_axis.Z)? 0 : _axis.Z * _sinHalfAngle;
|
||||||
|
W = dcos(_angle * 0.5);
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func FromBuffer(_buffer, _type)
|
||||||
|
///
|
||||||
|
/// @desc Loads quaternion components `(x, y, z, w)` from a buffer.
|
||||||
|
///
|
||||||
|
/// @param {Id.Buffer} _buffer The buffer to read the quaternion components
|
||||||
|
/// from.
|
||||||
|
///
|
||||||
|
/// @param {Constant.BufferDataType} [_type] The type of each component.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} Returns `self`.
|
||||||
|
static FromBuffer = function (_buffer, _type) {
|
||||||
|
INLINE
|
||||||
|
X = buffer_read(_buffer, _type);
|
||||||
|
Y = buffer_read(_buffer, _type);
|
||||||
|
Z = buffer_read(_buffer, _type);
|
||||||
|
W = buffer_read(_buffer, _type);
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func FromEuler(_x, _y, _z)
|
||||||
|
///
|
||||||
|
/// @desc Initializes the quaternion using euler angles.
|
||||||
|
///
|
||||||
|
/// @param {Real} _x The rotation around the X axis (in degrees).
|
||||||
|
/// @param {Real} _y The rotation around the Y axis (in degrees).
|
||||||
|
/// @param {Real} _z The rotation around the Z axis (in degrees).
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} Returns `self`.
|
||||||
|
///
|
||||||
|
/// @note The order of rotations is YXZ, same as in the `matrix_build`
|
||||||
|
/// function.
|
||||||
|
static FromEuler = function (_x, _y, _z) {
|
||||||
|
INLINE
|
||||||
|
|
||||||
|
_x = -_x * 0.5;
|
||||||
|
_y = -_y * 0.5;
|
||||||
|
_z = -_z * 0.5;
|
||||||
|
|
||||||
|
var _q1Sin, _q1Cos, _temp;
|
||||||
|
var _qX, _qY, _qZ, _qW;
|
||||||
|
|
||||||
|
_q1Sin = dsin(_z);
|
||||||
|
_q1Cos = dcos(_z);
|
||||||
|
|
||||||
|
_temp = dsin(_x);
|
||||||
|
|
||||||
|
_qX = _q1Cos * _temp;
|
||||||
|
_qY = _q1Sin * _temp;
|
||||||
|
|
||||||
|
_temp = dcos(_x);
|
||||||
|
|
||||||
|
_qZ = _q1Sin * _temp;
|
||||||
|
_qW = _q1Cos * _temp;
|
||||||
|
|
||||||
|
_q1Sin = dsin(_y);
|
||||||
|
_q1Cos = dcos(_y);
|
||||||
|
|
||||||
|
X = _qX * _q1Cos - _qZ * _q1Sin;
|
||||||
|
Y = _qW * _q1Sin + _qY * _q1Cos;
|
||||||
|
Z = _qZ * _q1Cos + _qX * _q1Sin;
|
||||||
|
W = _qW * _q1Cos - _qY * _q1Sin;
|
||||||
|
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func FromLookRotation(_forward, _up)
|
||||||
|
///
|
||||||
|
/// @desc Initializes the quaternion using a forward and an up vector. These
|
||||||
|
/// vectors must not be parallel! If they are, the quaternion will be set to an
|
||||||
|
/// identity.
|
||||||
|
///
|
||||||
|
/// @param {Struct.BBMOD_Vec3} _forward The vector facing forward.
|
||||||
|
/// @param {Struct.BBMOD_Vec3} _up The vector facing up.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} Returns `self`.
|
||||||
|
static FromLookRotation = function (_forward, _up) {
|
||||||
|
INLINE
|
||||||
|
|
||||||
|
_forward = new BBMOD_Vec3(_forward);
|
||||||
|
_up = new BBMOD_Vec3(_up);
|
||||||
|
|
||||||
|
if (!_forward.Orthonormalize(_up)) {
|
||||||
|
X = 0.0;
|
||||||
|
Y = 0.0;
|
||||||
|
Z = 0.0;
|
||||||
|
W = 1.0;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _right = _up.Cross(_forward);
|
||||||
|
var _w = sqrt(abs(1.0 + _right.X + _up.Y + _forward.Z)) * 0.5;
|
||||||
|
var _w4Recip = _w == 0? 0 : 1.0 / (4.0 * _w);
|
||||||
|
|
||||||
|
X = (_up.Z - _forward.Y) * _w4Recip;
|
||||||
|
Y = (_forward.X - _right.Z) * _w4Recip;
|
||||||
|
Z = (_right.Y - _up.X) * _w4Recip;
|
||||||
|
W = _w;
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
|
||||||
|
static FromMatrix = function(rotMatrix) {
|
||||||
|
INLINE
|
||||||
|
|
||||||
|
W = sqrt(1 + rotMatrix[0] + rotMatrix[5] + rotMatrix[10]) / 2;
|
||||||
|
X = (rotMatrix[9] - rotMatrix[6]) / (4 * W);
|
||||||
|
Y = (rotMatrix[2] - rotMatrix[8]) / (4 * W);
|
||||||
|
Z = (rotMatrix[4] - rotMatrix[1]) / (4 * W);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @func GetAngle()
|
||||||
|
///
|
||||||
|
/// @desc Retrieves the rotation angle of the quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Real} The rotation angle.
|
||||||
|
static GetAngle = function () {
|
||||||
|
INLINE
|
||||||
|
return radtodeg(arccos(W) * 2.0);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func GetAxis()
|
||||||
|
///
|
||||||
|
/// @desc Retrieves the axis of rotation of the quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Vec3} The axis of rotation.
|
||||||
|
static GetAxis = function () {
|
||||||
|
INLINE
|
||||||
|
var _sinThetaInv = 1.0 / sin(arccos(W));
|
||||||
|
return new BBMOD_Vec3(
|
||||||
|
X * _sinThetaInv,
|
||||||
|
Y * _sinThetaInv,
|
||||||
|
Z * _sinThetaInv
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Inverse()
|
||||||
|
///
|
||||||
|
/// @desc Computes an inverse of the quaternion and returns the result
|
||||||
|
/// as a new quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Inverse = function () {
|
||||||
|
INLINE
|
||||||
|
return Length() == 0? new BBMOD_Quaternion() : Conjugate().Scale(1.0 / Length());
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Length()
|
||||||
|
///
|
||||||
|
/// @desc Computes the length of the quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Real} The length of the quaternion.
|
||||||
|
static Length = function () {
|
||||||
|
INLINE
|
||||||
|
return sqrt(
|
||||||
|
X * X
|
||||||
|
+ Y * Y
|
||||||
|
+ Z * Z
|
||||||
|
+ W * W
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func LengthSqr()
|
||||||
|
///
|
||||||
|
/// @desc Computes a squared length of the quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Real} The squared length of the quaternion.
|
||||||
|
static LengthSqr = function () {
|
||||||
|
INLINE
|
||||||
|
return (
|
||||||
|
X * X
|
||||||
|
+ Y * Y
|
||||||
|
+ Z * Z
|
||||||
|
+ W * W
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Lerp(_q, _s)
|
||||||
|
///
|
||||||
|
/// @desc Computes a linear interpolation of two quaternions
|
||||||
|
/// and returns the result as a new quaternion.
|
||||||
|
///
|
||||||
|
/// @param {Struct.BBMOD_Quaternion} _q The other quaternion.
|
||||||
|
/// @param {Real} _s The interpolation factor.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Lerp = function (_q, _s) {
|
||||||
|
INLINE
|
||||||
|
return new BBMOD_Quaternion(
|
||||||
|
lerp(X, _q.X, _s),
|
||||||
|
lerp(Y, _q.Y, _s),
|
||||||
|
lerp(Z, _q.Z, _s),
|
||||||
|
lerp(W, _q.W, _s)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Log()
|
||||||
|
///
|
||||||
|
/// @desc Computes the logarithm map of the quaternion and returns the
|
||||||
|
/// result as a new quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Log = function () {
|
||||||
|
INLINE
|
||||||
|
var _length = Length();
|
||||||
|
var _w = logn(2.71828, _length);
|
||||||
|
var _a = arccos(W / _length);
|
||||||
|
if (_a >= math_get_epsilon())
|
||||||
|
{
|
||||||
|
var _mag = 1.0 / _length / Sinc(_a);
|
||||||
|
return new BBMOD_Quaternion(
|
||||||
|
X * _mag,
|
||||||
|
Y * _mag,
|
||||||
|
Z * _mag,
|
||||||
|
_w
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return new BBMOD_Quaternion(0.0, 0.0, 0.0, _w);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Mul(_q)
|
||||||
|
///
|
||||||
|
/// @desc Multiplies two quaternions and returns the result as a new
|
||||||
|
/// quaternion.
|
||||||
|
///
|
||||||
|
/// @param {Struct.BBMOD_Quaternion} _q The other quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Mul = function (_q) {
|
||||||
|
INLINE
|
||||||
|
return new BBMOD_Quaternion(
|
||||||
|
W * _q.X + X * _q.W + Y * _q.Z - Z * _q.Y,
|
||||||
|
W * _q.Y + Y * _q.W + Z * _q.X - X * _q.Z,
|
||||||
|
W * _q.Z + Z * _q.W + X * _q.Y - Y * _q.X,
|
||||||
|
W * _q.W - X * _q.X - Y * _q.Y - Z * _q.Z
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Normalize()
|
||||||
|
///
|
||||||
|
/// @desc Normalizes the quaternion and returns the result as a new
|
||||||
|
/// quaternion.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Normalize = function () {
|
||||||
|
INLINE
|
||||||
|
var _lengthSqr = LengthSqr();
|
||||||
|
|
||||||
|
if(_lengthSqr == 0)
|
||||||
|
return new BBMOD_Quaternion();
|
||||||
|
|
||||||
|
if (_lengthSqr >= math_get_epsilon())
|
||||||
|
return Scale(1.0 / sqrt(_lengthSqr));
|
||||||
|
return Clone();
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Rotate(_v)
|
||||||
|
///
|
||||||
|
/// @desc Rotates a vector using the quaternion and returns the result
|
||||||
|
/// as a new vector.
|
||||||
|
///
|
||||||
|
/// @param {Struct.BBMOD_Vec3} _v The vector to rotate.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Vec3} The created vector.
|
||||||
|
static Rotate = function (_v) {
|
||||||
|
INLINE
|
||||||
|
|
||||||
|
var _tovec = is_instanceof(_v, __vec3);
|
||||||
|
if(_tovec) _v = new BBMOD_Vec3(_v.x, _v.y, _v.z);
|
||||||
|
|
||||||
|
var _q = Normalize();
|
||||||
|
var _V = new BBMOD_Quaternion(_v.X, _v.Y, _v.Z, 0.0);
|
||||||
|
var _rot = _q.Mul(_V).Mul(_q.Conjugate());
|
||||||
|
|
||||||
|
var res;
|
||||||
|
if(_tovec) res = new __vec3(_rot.X, _rot.Y, _rot.Z);
|
||||||
|
else res = new BBMOD_Vec3(_rot.X, _rot.Y, _rot.Z);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Scale(_s)
|
||||||
|
///
|
||||||
|
/// @desc Scales each component of the quaternion by a real value and
|
||||||
|
/// returns the result as a new quaternion.
|
||||||
|
///
|
||||||
|
/// @param {Real} _s The value to scale the quaternion by.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Scale = function (_s) {
|
||||||
|
INLINE
|
||||||
|
return new BBMOD_Quaternion(
|
||||||
|
X * _s,
|
||||||
|
Y * _s,
|
||||||
|
Z * _s,
|
||||||
|
W * _s
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
static Sinc = function (_x) {
|
||||||
|
INLINE
|
||||||
|
return (_x >= math_get_epsilon()) ? (sin(_x) / _x) : 1.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func Slerp(_q, _s)
|
||||||
|
///
|
||||||
|
/// @desc Computes a spherical linear interpolation of two quaternions
|
||||||
|
/// and returns the result as a new quaternion.
|
||||||
|
///
|
||||||
|
/// @param {Struct.BBMOD_Quaternion} _q The other quaternion.
|
||||||
|
/// @param {Real} _s The interpolation factor.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} The created quaternion.
|
||||||
|
static Slerp = function (_q, _s) {
|
||||||
|
INLINE
|
||||||
|
|
||||||
|
var _q10 = X;
|
||||||
|
var _q11 = Y;
|
||||||
|
var _q12 = Z;
|
||||||
|
var _q13 = W;
|
||||||
|
|
||||||
|
var _q20 = _q.X;
|
||||||
|
var _q21 = _q.Y;
|
||||||
|
var _q22 = _q.Z;
|
||||||
|
var _q23 = _q.W;
|
||||||
|
|
||||||
|
var _norm;
|
||||||
|
|
||||||
|
_norm = 1.0 / sqrt(_q10 * _q10
|
||||||
|
+ _q11 * _q11
|
||||||
|
+ _q12 * _q12
|
||||||
|
+ _q13 * _q13);
|
||||||
|
|
||||||
|
_q10 *= _norm;
|
||||||
|
_q11 *= _norm;
|
||||||
|
_q12 *= _norm;
|
||||||
|
_q13 *= _norm;
|
||||||
|
|
||||||
|
_norm = sqrt(_q20 * _q20
|
||||||
|
+ _q21 * _q21
|
||||||
|
+ _q22 * _q22
|
||||||
|
+ _q23 * _q23);
|
||||||
|
|
||||||
|
_q20 *= _norm;
|
||||||
|
_q21 *= _norm;
|
||||||
|
_q22 *= _norm;
|
||||||
|
_q23 *= _norm;
|
||||||
|
|
||||||
|
var _dot = _q10 * _q20
|
||||||
|
+ _q11 * _q21
|
||||||
|
+ _q12 * _q22
|
||||||
|
+ _q13 * _q23;
|
||||||
|
|
||||||
|
if (_dot < 0.0)
|
||||||
|
{
|
||||||
|
_dot = -_dot;
|
||||||
|
_q20 *= -1.0;
|
||||||
|
_q21 *= -1.0;
|
||||||
|
_q22 *= -1.0;
|
||||||
|
_q23 *= -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_dot > 0.9995)
|
||||||
|
{
|
||||||
|
return new BBMOD_Quaternion(
|
||||||
|
lerp(_q10, _q20, _s),
|
||||||
|
lerp(_q11, _q21, _s),
|
||||||
|
lerp(_q12, _q22, _s),
|
||||||
|
lerp(_q13, _q23, _s)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var _theta0 = arccos(_dot);
|
||||||
|
var _theta = _theta0 * _s;
|
||||||
|
var _sinTheta = sin(_theta);
|
||||||
|
var _sinTheta0 = sin(_theta0);
|
||||||
|
var _s2 = _sinTheta / _sinTheta0;
|
||||||
|
var _s1 = cos(_theta) - (_dot * _s2);
|
||||||
|
|
||||||
|
return new BBMOD_Quaternion(
|
||||||
|
(_q10 * _s1) + (_q20 * _s2),
|
||||||
|
(_q11 * _s1) + (_q21 * _s2),
|
||||||
|
(_q12 * _s1) + (_q22 * _s2),
|
||||||
|
(_q13 * _s1) + (_q23 * _s2)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func ToArray([_array[, _index]])
|
||||||
|
///
|
||||||
|
/// @desc Writes components `(x, y, z, w)` of the quaternion into an array.
|
||||||
|
///
|
||||||
|
/// @param {Array<Real>} [_array] The destination array. If not defined, a
|
||||||
|
/// new one is created.
|
||||||
|
/// @param {Real} [_index] The index to start writing to. Defaults to 0.
|
||||||
|
///
|
||||||
|
/// @return {Array<Real>} Returns the destination array.
|
||||||
|
static ToArray = function (_array=undefined, _index=0) {
|
||||||
|
INLINE
|
||||||
|
_array ??= array_create(4, 0.0);
|
||||||
|
_array[@ _index] = X;
|
||||||
|
_array[@ _index + 1] = Y;
|
||||||
|
_array[@ _index + 2] = Z;
|
||||||
|
_array[@ _index + 3] = W;
|
||||||
|
return _array;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @func ToBuffer(_buffer, _type)
|
||||||
|
///
|
||||||
|
/// @desc Writes the quaternion into a buffer.
|
||||||
|
///
|
||||||
|
/// @param {Id.Buffer} _buffer The buffer to write the quaternion to.
|
||||||
|
/// @param {Constant.BufferDataType} _type The type of each component.
|
||||||
|
///
|
||||||
|
/// @return {Struct.BBMOD_Quaternion} Returns `self`.
|
||||||
|
static ToBuffer = function (_buffer, _type) {
|
||||||
|
INLINE
|
||||||
|
buffer_write(_buffer, _type, X);
|
||||||
|
buffer_write(_buffer, _type, Y);
|
||||||
|
buffer_write(_buffer, _type, Z);
|
||||||
|
buffer_write(_buffer, _type, W);
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
|
||||||
|
static ToEuler = function(isArray = false) {
|
||||||
|
var ysqr = Y * Y;
|
||||||
|
|
||||||
|
// roll (x-axis rotation)
|
||||||
|
var t0 = +2.0 * (W * X + Y * Z);
|
||||||
|
var t1 = +1.0 - 2.0 * (X * X + ysqr);
|
||||||
|
var roll = arctan2(t0, t1);
|
||||||
|
|
||||||
|
// pitch (y-axis rotation)
|
||||||
|
var t2 = +2.0 * (W * Y - Z * X);
|
||||||
|
t2 = clamp(t2, -1.0, 1.0); // Prevent numerical instability
|
||||||
|
var pitch = arcsin(t2);
|
||||||
|
|
||||||
|
// yaw (z-axis rotation)
|
||||||
|
var t3 = +2.0 * (W * Z + X * Y);
|
||||||
|
var t4 = +1.0 - 2.0 * (ysqr + Z * Z);
|
||||||
|
var yaw = arctan2(t3, t4);
|
||||||
|
|
||||||
|
// Convert radians to degrees
|
||||||
|
var _dx = roll * 180.0 / pi;
|
||||||
|
var _dy = pitch * 180.0 / pi;
|
||||||
|
var _dz = yaw * 180.0 / pi;
|
||||||
|
|
||||||
|
_dx = round(_dx * 1000) / 1000;
|
||||||
|
_dy = round(_dy * 1000) / 1000;
|
||||||
|
_dz = round(_dz * 1000) / 1000;
|
||||||
|
|
||||||
|
return isArray? [ _dx, _dy, _dz ] : new __rot3(_dx, _dy, _dz);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @func ToMatrix([_dest[, _index]])
|
||||||
|
///
|
||||||
|
/// @desc Converts quaternion into a matrix.
|
||||||
|
///
|
||||||
|
/// @param {Array<Real>} [_dest] The destination array. If not specified, a
|
||||||
|
/// new one is created.
|
||||||
|
/// @param {Real} [_index] The starting index in the destination array.
|
||||||
|
/// Defaults to 0.
|
||||||
|
///
|
||||||
|
/// @return {Array<Real>} Returns the destination array.
|
||||||
|
static ToMatrix = function (_dest=undefined, _index=0) {
|
||||||
|
INLINE
|
||||||
|
|
||||||
|
_dest ??= matrix_build_identity();
|
||||||
|
|
||||||
|
if(is_nan(X)) return _dest;
|
||||||
|
|
||||||
|
var _norm = Normalize();
|
||||||
|
|
||||||
|
var _temp0, _temp1, _temp2;
|
||||||
|
var _q0 = _norm.X;
|
||||||
|
var _q1 = _norm.Y;
|
||||||
|
var _q2 = _norm.Z;
|
||||||
|
var _q3 = _norm.W;
|
||||||
|
|
||||||
|
_temp0 = _q0 * _q0;
|
||||||
|
_temp1 = _q1 * _q1;
|
||||||
|
_temp2 = _q2 * _q2;
|
||||||
|
_dest[@ _index] = 1.0 - 2.0 * (_temp1 + _temp2);
|
||||||
|
_dest[@ _index + 5] = 1.0 - 2.0 * (_temp0 + _temp2);
|
||||||
|
_dest[@ _index + 10] = 1.0 - 2.0 * (_temp0 + _temp1);
|
||||||
|
|
||||||
|
_temp0 = _q0 * _q1;
|
||||||
|
_temp1 = _q3 * _q2;
|
||||||
|
_dest[@ _index + 1] = 2.0 * (_temp0 + _temp1);
|
||||||
|
_dest[@ _index + 4] = 2.0 * (_temp0 - _temp1);
|
||||||
|
|
||||||
|
_temp0 = _q0 * _q2
|
||||||
|
_temp1 = _q3 * _q1;
|
||||||
|
_dest[@ _index + 2] = 2.0 * (_temp0 - _temp1);
|
||||||
|
_dest[@ _index + 8] = 2.0 * (_temp0 + _temp1);
|
||||||
|
|
||||||
|
_temp0 = _q1 * _q2;
|
||||||
|
_temp1 = _q3 * _q0;
|
||||||
|
_dest[@ _index + 6] = 2.0 * (_temp0 + _temp1);
|
||||||
|
_dest[@ _index + 9] = 2.0 * (_temp0 - _temp1);
|
||||||
|
|
||||||
|
return _dest;
|
||||||
|
};
|
||||||
|
}
|
86
#backups/scripts/__node_3d/__node_3d.gml.backup0
Normal file
86
#backups/scripts/__node_3d/__node_3d.gml.backup0
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
// 2024-05-01 16:00:45
|
||||||
|
function Node_3D(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
|
||||||
|
name = "3D";
|
||||||
|
is_3D = true;
|
||||||
|
surface_depth_disable(false);
|
||||||
|
|
||||||
|
mesh_prev_surface = surface_create(64, 64);
|
||||||
|
|
||||||
|
static drawOverlay3D = function(active, params, _mx, _my, _snx, _sny, _panel) {}
|
||||||
|
|
||||||
|
static processData = function(_outSurf, _data, _output_index, _array_index) {}
|
||||||
|
static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) {}
|
||||||
|
|
||||||
|
static getPreviewObject = function() { #region
|
||||||
|
if(ds_list_empty(outputs)) return noone;
|
||||||
|
|
||||||
|
switch(outputs[| preview_channel].type) {
|
||||||
|
case VALUE_TYPE.d3Mesh :
|
||||||
|
case VALUE_TYPE.d3Light :
|
||||||
|
case VALUE_TYPE.d3Camera :
|
||||||
|
case VALUE_TYPE.d3Scene : break;
|
||||||
|
|
||||||
|
default : return noone;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _obj = outputs[| 0].getValue();
|
||||||
|
if(is_array(_obj)) _obj = array_safe_get_fast(_obj, preview_index, noone);
|
||||||
|
|
||||||
|
return _obj;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static getPreviewObjects = function() { return [ getPreviewObject() ]; }
|
||||||
|
|
||||||
|
static getPreviewObjectOutline = function() { return getPreviewObjects() }
|
||||||
|
|
||||||
|
static refreshPreview = function() { #region
|
||||||
|
var _prev_obj = getPreviewObjects();
|
||||||
|
|
||||||
|
mesh_prev_surface = surface_verify(mesh_prev_surface, PREFERENCES.node_3d_preview_size, PREFERENCES.node_3d_preview_size);
|
||||||
|
surface_set_target(mesh_prev_surface);
|
||||||
|
DRAW_CLEAR
|
||||||
|
|
||||||
|
gpu_set_zwriteenable(true);
|
||||||
|
gpu_set_ztestenable(true);
|
||||||
|
gpu_set_cullmode(cull_noculling);
|
||||||
|
|
||||||
|
D3D_GLOBAL_PREVIEW.camera.applyCamera();
|
||||||
|
D3D_GLOBAL_PREVIEW.apply();
|
||||||
|
|
||||||
|
for( var i = 0, n = array_length(_prev_obj); i < n; i++ ) {
|
||||||
|
var _prev = _prev_obj[i];
|
||||||
|
if(!is_struct(_prev) || !struct_has(_prev, "getBBOX")) continue;
|
||||||
|
|
||||||
|
var _b = _prev.getBBOX();
|
||||||
|
var _c = _prev.getCenter();
|
||||||
|
if(_b == noone || _c == noone) continue;
|
||||||
|
|
||||||
|
D3D_GLOBAL_PREVIEW.custom_transform.position.set(_c._multiply(-1));
|
||||||
|
|
||||||
|
var _sca = 2 / _b.getScale();
|
||||||
|
//print($"Submitting object {_prev}\n{_b}, {_c}, {_sca}");
|
||||||
|
|
||||||
|
D3D_GLOBAL_PREVIEW.custom_transform.scale.set(_sca);
|
||||||
|
D3D_GLOBAL_PREVIEW.submitUI(_prev);
|
||||||
|
}
|
||||||
|
surface_reset_target();
|
||||||
|
|
||||||
|
D3D_GLOBAL_PREVIEW.camera.resetCamera();
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static postProcess = function() { refreshPreview(); }
|
||||||
|
|
||||||
|
static onDrawNode = function(xx, yy, _mx, _my, _s, _hover = false, _focus = false) { #region
|
||||||
|
if(!is_surface(mesh_prev_surface)) return;
|
||||||
|
if(!previewable) return;
|
||||||
|
|
||||||
|
var bbox = drawGetBbox(xx, yy, _s);
|
||||||
|
var aa = 0.5 + 0.5 * renderActive;
|
||||||
|
if(!isHighlightingInGraph()) aa *= 0.25;
|
||||||
|
|
||||||
|
draw_surface_bbox(mesh_prev_surface, bbox,, aa);
|
||||||
|
onDrawNodeOver(xx, yy, _mx, _my, _s, _hover, _focus);
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static onDrawNodeOver = function(xx, yy, _mx, _my, _s, _hover = false, _focus = false) { }
|
||||||
|
}
|
86
#backups/scripts/__node_3d/__node_3d.gml.backup1
Normal file
86
#backups/scripts/__node_3d/__node_3d.gml.backup1
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
// 2024-05-01 16:00:18
|
||||||
|
function Node_3D(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
|
||||||
|
name = "3D";
|
||||||
|
is_3D = true;
|
||||||
|
surface_depth_disable(false);
|
||||||
|
|
||||||
|
mesh_prev_surface = surface_create(64, 64);
|
||||||
|
|
||||||
|
static drawOverlay3D = function(active, params, _mx, _my, _snx, _sny, _panel) {}
|
||||||
|
|
||||||
|
static processData = function(_outSurf, _data, _output_index, _array_index) {}
|
||||||
|
static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) {}
|
||||||
|
|
||||||
|
static getPreviewObject = function() { #region
|
||||||
|
if(ds_list_empty(outputs)) return noone;
|
||||||
|
|
||||||
|
switch(outputs[| preview_channel].type) {
|
||||||
|
case VALUE_TYPE.d3Mesh :
|
||||||
|
case VALUE_TYPE.d3Light :
|
||||||
|
case VALUE_TYPE.d3Camera :
|
||||||
|
case VALUE_TYPE.d3Scene : break;
|
||||||
|
|
||||||
|
default : return noone;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _obj = outputs[| 0].getValue();
|
||||||
|
if(is_array(_obj)) _obj = array_safe_get_fast(_obj, preview_index, noone);
|
||||||
|
|
||||||
|
return _obj;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static getPreviewObjects = function() { return [ getPreviewObject() ]; }
|
||||||
|
|
||||||
|
static getPreviewObjectOutline = function() { return getPreviewObjects() }
|
||||||
|
|
||||||
|
static refreshPreview = function() { #region
|
||||||
|
var _prev_obj = getPreviewObjects();
|
||||||
|
|
||||||
|
mesh_prev_surface = surface_verify(mesh_prev_surface, PREFERENCES.node_3d_preview_size, PREFERENCES.node_3d_preview_size);
|
||||||
|
surface_set_target(mesh_prev_surface);
|
||||||
|
DRAW_CLEAR
|
||||||
|
|
||||||
|
gpu_set_zwriteenable(true);
|
||||||
|
gpu_set_ztestenable(true);
|
||||||
|
gpu_set_cullmode(cull_noculling);
|
||||||
|
|
||||||
|
D3D_GLOBAL_PREVIEW.camera.applyCamera();
|
||||||
|
D3D_GLOBAL_PREVIEW.apply();
|
||||||
|
|
||||||
|
for( var i = 0, n = array_length(_prev_obj); i < n; i++ ) {
|
||||||
|
var _prev = _prev_obj[i];
|
||||||
|
if(!is_struct(_prev) || !struct_has(_prev, "getBBOX")) continue;
|
||||||
|
|
||||||
|
var _b = _prev.getBBOX();
|
||||||
|
var _c = _prev.getCenter();
|
||||||
|
if(_b == noone || _c == noone) continue;
|
||||||
|
|
||||||
|
D3D_GLOBAL_PREVIEW.custom_transform.position.set(_c._multiply(-1));
|
||||||
|
|
||||||
|
var _sca = 2 / _b.getScale();
|
||||||
|
//print($"Submitting object {_prev}\n{_b}, {_c}, {_sca}");
|
||||||
|
|
||||||
|
D3D_GLOBAL_PREVIEW.custom_transform.scale.set(_sca);
|
||||||
|
D3D_GLOBAL_PREVIEW.submitUI(_prev);
|
||||||
|
}
|
||||||
|
surface_reset_target();
|
||||||
|
|
||||||
|
D3D_GLOBAL_PREVIEW.camera.resetCamera();
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static postProcess = function() { refreshPreview(); }
|
||||||
|
|
||||||
|
static onDrawNode = function(xx, yy, _mx, _my, _s, _hover = false, _focus = false) { #region
|
||||||
|
if(!is_surface(mesh_prev_surface)) return;
|
||||||
|
if(!previewable) return;
|
||||||
|
|
||||||
|
var bbox = drawGetBbox(xx, yy, _s);
|
||||||
|
var aa = 0.5 + 0.5 * renderActive;
|
||||||
|
if(!isHighlightingInGraph()) aa *= 0.25;
|
||||||
|
|
||||||
|
draw_surface_bbox(mesh_prev_surface, bbox,, aa);
|
||||||
|
onDrawNodeOver(xx, yy, _mx, _my, _s, _hover, _focus);
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static onDrawNodeOver = function(xx, yy, _mx, _my, _s, _hover = false, _focus = false) { }
|
||||||
|
}
|
633
#backups/scripts/__node_3d_object/__node_3d_object.gml.backup0
Normal file
633
#backups/scripts/__node_3d_object/__node_3d_object.gml.backup0
Normal file
|
@ -0,0 +1,633 @@
|
||||||
|
// 2024-05-01 16:28:40
|
||||||
|
function Node_3D_Object(_x, _y, _group = noone) : Node_3D(_x, _y, _group) constructor {
|
||||||
|
name = "3D Object";
|
||||||
|
cached_object = [];
|
||||||
|
object_class = noone;
|
||||||
|
|
||||||
|
preview_channel = 0;
|
||||||
|
|
||||||
|
inputs[| 0] = nodeValue("Position", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0, 0 ])
|
||||||
|
.setDisplay(VALUE_DISPLAY.vector);
|
||||||
|
|
||||||
|
inputs[| 1] = nodeValue("Rotation", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0, 0, 1 ])
|
||||||
|
.setDisplay(VALUE_DISPLAY.d3quarternion);
|
||||||
|
|
||||||
|
inputs[| 2] = nodeValue("Scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 1, 1, 1 ])
|
||||||
|
.setDisplay(VALUE_DISPLAY.vector);
|
||||||
|
|
||||||
|
inputs[| 3] = nodeValue("Anchor", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0, 0 ])
|
||||||
|
.setDisplay(VALUE_DISPLAY.vector);
|
||||||
|
|
||||||
|
in_d3d = ds_list_size(inputs);
|
||||||
|
|
||||||
|
#macro __d3d_input_list_transform ["Transform", false], 0, 3, 1, 2
|
||||||
|
|
||||||
|
#region ---- overlay ----
|
||||||
|
drag_axis = noone;
|
||||||
|
drag_sv = 0;
|
||||||
|
drag_delta = 0;
|
||||||
|
drag_prev = 0;
|
||||||
|
drag_dist = 0;
|
||||||
|
drag_val = 0;
|
||||||
|
|
||||||
|
drag_mx = 0;
|
||||||
|
drag_my = 0;
|
||||||
|
drag_px = 0;
|
||||||
|
drag_py = 0;
|
||||||
|
drag_cx = 0;
|
||||||
|
drag_cy = 0;
|
||||||
|
drag_rot_axis = new BBMOD_Quaternion();
|
||||||
|
|
||||||
|
drag_original = 0;
|
||||||
|
|
||||||
|
axis_hover = noone;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ---- tools ----
|
||||||
|
tool_pos = new NodeTool( "Transform", THEME.tools_3d_transform, "Node_3D_Object" );
|
||||||
|
tool_rot = new NodeTool( "Rotate", THEME.tools_3d_rotate, "Node_3D_Object" );
|
||||||
|
tool_sca = new NodeTool( "Scale", THEME.tools_3d_scale, "Node_3D_Object" );
|
||||||
|
tools = [ tool_pos, tool_rot, tool_sca ];
|
||||||
|
|
||||||
|
tool_axis_edit = new scrollBox([ "local", "global" ], function(val) { tool_attribute.context = val; });
|
||||||
|
// tool_axis_edit.font = f_p2;
|
||||||
|
// tool_axis_edit.arrow_spr = THEME.arrow;
|
||||||
|
// tool_axis_edit.arrow_ind = 3;
|
||||||
|
tool_attribute.context = 0;
|
||||||
|
tool_settings = [
|
||||||
|
[ "Axis", tool_axis_edit, "context", tool_attribute ],
|
||||||
|
];
|
||||||
|
|
||||||
|
static getToolSettings = function() {
|
||||||
|
if(isUsingTool("Transform") || isUsingTool("Rotate"))
|
||||||
|
return tool_settings;
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
static drawGizmoPosition = function(index, object, _vpos, active, params, _mx, _my, _snx, _sny, _panel) { #region
|
||||||
|
#region ---- main ----
|
||||||
|
var _pos = inputs[| index].getValue(,,, true);
|
||||||
|
var _qrot = object == noone? new BBMOD_Quaternion() : object.transform.rotation;
|
||||||
|
var _qinv = new BBMOD_Quaternion().FromAxisAngle(new BBMOD_Vec3(1, 0, 0), 90);
|
||||||
|
|
||||||
|
var _camera = params.camera;
|
||||||
|
var _qview = new BBMOD_Quaternion().FromEuler(_camera.focus_angle_y, -_camera.focus_angle_x, 0);
|
||||||
|
|
||||||
|
var _axis = tool_attribute.context;
|
||||||
|
|
||||||
|
var _hover = noone;
|
||||||
|
var _hoverDist = 10;
|
||||||
|
var th;
|
||||||
|
|
||||||
|
var _posView = _camera.worldPointToViewPoint(_vpos);
|
||||||
|
|
||||||
|
var cx = _posView.x;
|
||||||
|
var cy = _posView.y;
|
||||||
|
|
||||||
|
var ga = [];
|
||||||
|
var size = 64;
|
||||||
|
var hs = size / 2;
|
||||||
|
var sq = 8;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region display
|
||||||
|
ga[0] = new BBMOD_Vec3(-size, 0, 0);
|
||||||
|
ga[1] = new BBMOD_Vec3(0, 0, size);
|
||||||
|
ga[2] = new BBMOD_Vec3(0, -size, 0);
|
||||||
|
|
||||||
|
ga[3] = [ new BBMOD_Vec3(-hs + sq, 0, hs - sq),
|
||||||
|
new BBMOD_Vec3(-hs - sq, 0, hs - sq),
|
||||||
|
new BBMOD_Vec3(-hs - sq, 0, hs + sq),
|
||||||
|
new BBMOD_Vec3(-hs + sq, 0, hs + sq), ];
|
||||||
|
ga[4] = [ new BBMOD_Vec3( 0, -hs + sq, hs - sq),
|
||||||
|
new BBMOD_Vec3( 0, -hs - sq, hs - sq),
|
||||||
|
new BBMOD_Vec3( 0, -hs - sq, hs + sq),
|
||||||
|
new BBMOD_Vec3( 0, -hs + sq, hs + sq), ];
|
||||||
|
ga[5] = [ new BBMOD_Vec3(-hs + sq, -hs - sq, 0),
|
||||||
|
new BBMOD_Vec3(-hs - sq, -hs - sq, 0),
|
||||||
|
new BBMOD_Vec3(-hs - sq, -hs + sq, 0),
|
||||||
|
new BBMOD_Vec3(-hs + sq, -hs + sq, 0), ];
|
||||||
|
|
||||||
|
ga[0] = new BBMOD_Vec3(-size, 0, 0);
|
||||||
|
ga[1] = new BBMOD_Vec3(0, -size, 0);
|
||||||
|
ga[2] = new BBMOD_Vec3(0, 0, -size);
|
||||||
|
|
||||||
|
ga[3] = [ new BBMOD_Vec3(-hs + sq, -hs - sq, 0),
|
||||||
|
new BBMOD_Vec3(-hs - sq, -hs - sq, 0),
|
||||||
|
new BBMOD_Vec3(-hs - sq, -hs + sq, 0),
|
||||||
|
new BBMOD_Vec3(-hs + sq, -hs + sq, 0), ];
|
||||||
|
ga[4] = [ new BBMOD_Vec3( 0, -hs + sq, -hs - sq),
|
||||||
|
new BBMOD_Vec3( 0, -hs - sq, -hs - sq),
|
||||||
|
new BBMOD_Vec3( 0, -hs - sq, -hs + sq),
|
||||||
|
new BBMOD_Vec3( 0, -hs + sq, -hs + sq), ];
|
||||||
|
ga[5] = [ new BBMOD_Vec3(-hs + sq, 0, -hs - sq),
|
||||||
|
new BBMOD_Vec3(-hs - sq, 0, -hs - sq),
|
||||||
|
new BBMOD_Vec3(-hs - sq, 0, -hs + sq),
|
||||||
|
new BBMOD_Vec3(-hs + sq, 0, -hs + sq), ];
|
||||||
|
|
||||||
|
for( var i = 0; i < 3; i++ ) {
|
||||||
|
if(_axis == 0)
|
||||||
|
ga[i] = _qview.Rotate(_qinv.Rotate(_qrot.Rotate(ga[i])));
|
||||||
|
else if(_axis == 1)
|
||||||
|
ga[i] = _qview.Rotate(_qinv.Rotate(ga[i]));
|
||||||
|
|
||||||
|
th = 2 + (axis_hover == i || drag_axis == i);
|
||||||
|
if(drag_axis != noone && drag_axis != i)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
draw_set_color(COLORS.axis[i]);
|
||||||
|
if(point_distance(cx, cy, cx + ga[i].X, cy + ga[i].Y) < 5)
|
||||||
|
draw_line_round(cx, cy, cx + ga[i].X, cy + ga[i].Y, th);
|
||||||
|
else
|
||||||
|
draw_line_round_arrow(cx, cy, cx + ga[i].X, cy + ga[i].Y, th, 3);
|
||||||
|
|
||||||
|
var _d = distance_to_line(_mx, _my, cx, cy, cx + ga[i].X, cy + ga[i].Y);
|
||||||
|
if(_d < _hoverDist) {
|
||||||
|
_hover = i;
|
||||||
|
_hoverDist = _d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( var i = 3; i < 6; i++ ) {
|
||||||
|
for( var j = 0; j < 4; j++ ) {
|
||||||
|
if(_axis == 0)
|
||||||
|
ga[i][j] = _qview.Rotate(_qinv.Rotate(_qrot.Rotate(ga[i][j])));
|
||||||
|
else if(_axis == 1)
|
||||||
|
ga[i][j] = _qview.Rotate(_qinv.Rotate(ga[i][j]));
|
||||||
|
}
|
||||||
|
|
||||||
|
th = 1;
|
||||||
|
|
||||||
|
var p0x = cx + ga[i][0].X, p0y = cy + ga[i][0].Y;
|
||||||
|
var p1x = cx + ga[i][1].X, p1y = cy + ga[i][1].Y;
|
||||||
|
var p2x = cx + ga[i][2].X, p2y = cy + ga[i][2].Y;
|
||||||
|
var p3x = cx + ga[i][3].X, p3y = cy + ga[i][3].Y;
|
||||||
|
|
||||||
|
var _pax = (p0x + p1x + p2x + p3x) / 4;
|
||||||
|
var _pay = (p0y + p1y + p2y + p3y) / 4;
|
||||||
|
|
||||||
|
if((abs(p0x - _pax) + abs(p1x - _pax) + abs(p2x - _pax) + abs(p3x - _pax)) / 4 < 1)
|
||||||
|
continue;
|
||||||
|
if((abs(p0y - _pay) + abs(p1y - _pay) + abs(p2y - _pay) + abs(p3y - _pay)) / 4 < 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
draw_set_color(COLORS.axis[(i - 3 - 1 + 3) % 3]);
|
||||||
|
if(axis_hover == i || drag_axis == i) {
|
||||||
|
draw_primitive_begin(pr_trianglestrip);
|
||||||
|
draw_vertex(p0x, p0y);
|
||||||
|
draw_vertex(p1x, p1y);
|
||||||
|
draw_vertex(p3x, p3y);
|
||||||
|
draw_vertex(p2x, p2y);
|
||||||
|
draw_primitive_end();
|
||||||
|
} else if (drag_axis == noone) {
|
||||||
|
draw_line(p0x, p0y, p1x, p1y);
|
||||||
|
draw_line(p1x, p1y, p2x, p2y);
|
||||||
|
draw_line(p2x, p2y, p3x, p3y);
|
||||||
|
draw_line(p3x, p3y, p0x, p0y);
|
||||||
|
} else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(point_in_rectangle_points(_mx, _my, p0x, p0y, p1x, p1y, p3x, p3y, p2x, p2y))
|
||||||
|
_hover = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
axis_hover = _hover;
|
||||||
|
#endregion display
|
||||||
|
|
||||||
|
if(drag_axis != noone) { #region editing
|
||||||
|
if(!MOUSE_WRAPPING) {
|
||||||
|
drag_mx += _mx - drag_px;
|
||||||
|
drag_my += _my - drag_py;
|
||||||
|
|
||||||
|
var mAdj, nor, prj;
|
||||||
|
|
||||||
|
var ray = _camera.viewPointToWorldRay(drag_mx, drag_my);
|
||||||
|
var val = [ drag_val[0], drag_val[1], drag_val[2] ];
|
||||||
|
|
||||||
|
if(drag_axis < 3) {
|
||||||
|
switch(drag_axis) {
|
||||||
|
case 0 : nor = new __vec3(0, 1, 0); prj = new __vec3(1, 0, 0); break;
|
||||||
|
case 1 : nor = new __vec3(0, 0, 1); prj = new __vec3(0, 1, 0); break;
|
||||||
|
case 2 : nor = new __vec3(1, 0, 0); prj = new __vec3(0, 0, 1); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_axis == 0) {
|
||||||
|
nor = _qrot.Rotate(nor);
|
||||||
|
prj = _qrot.Rotate(prj);
|
||||||
|
}
|
||||||
|
|
||||||
|
var pln = new __plane(drag_original, nor);
|
||||||
|
mAdj = d3d_intersect_ray_plane(ray, pln);
|
||||||
|
|
||||||
|
if(drag_prev != undefined) {
|
||||||
|
var _diff = mAdj.subtract(drag_prev);
|
||||||
|
var _dist = _diff.dot(prj);
|
||||||
|
|
||||||
|
for( var i = 0; i < 3; i++ )
|
||||||
|
val[i] += prj.getIndex(i) * _dist;
|
||||||
|
|
||||||
|
if(inputs[| index].setValue(value_snap(val, _snx)))
|
||||||
|
UNDO_HOLDING = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch(drag_axis) {
|
||||||
|
case 3 : nor = new __vec3(0, 0, 1); break;
|
||||||
|
case 4 : nor = new __vec3(1, 0, 0); break;
|
||||||
|
case 5 : nor = new __vec3(0, 1, 0); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_axis == 0)
|
||||||
|
nor = _qrot.Rotate(nor);
|
||||||
|
|
||||||
|
var pln = new __plane(drag_original, nor);
|
||||||
|
mAdj = d3d_intersect_ray_plane(ray, pln);
|
||||||
|
|
||||||
|
if(drag_prev != undefined) {
|
||||||
|
var _diff = mAdj.subtract(drag_prev);
|
||||||
|
|
||||||
|
for( var i = 0; i < 3; i++ )
|
||||||
|
val[i] += _diff.getIndex(i);
|
||||||
|
|
||||||
|
if(inputs[| index].setValue(value_snap(val, _snx)))
|
||||||
|
UNDO_HOLDING = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drag_val = [ val[0], val[1], val[2] ];
|
||||||
|
drag_prev = mAdj;
|
||||||
|
}
|
||||||
|
|
||||||
|
setMouseWrap();
|
||||||
|
drag_px = _mx;
|
||||||
|
drag_py = _my;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
if(_hover != noone && mouse_press(mb_left, active)) { #region
|
||||||
|
drag_axis = _hover;
|
||||||
|
drag_prev = undefined;
|
||||||
|
drag_mx = _mx;
|
||||||
|
drag_my = _my;
|
||||||
|
drag_px = _mx;
|
||||||
|
drag_py = _my;
|
||||||
|
drag_cx = cx;
|
||||||
|
drag_cy = cy;
|
||||||
|
|
||||||
|
drag_val = _pos;
|
||||||
|
drag_original = new __vec3(_pos);
|
||||||
|
} #endregion
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static drawGizmoRotation = function(index, object, _vpos, active, params, _mx, _my, _snx, _sny, _panel) { #region
|
||||||
|
#region ---- main ----
|
||||||
|
var _rot = inputs[| index].getValue();
|
||||||
|
var _qrot = object == noone? new BBMOD_Quaternion() : object.transform.rotation;
|
||||||
|
var _qinv = new BBMOD_Quaternion().FromAxisAngle(new BBMOD_Vec3(1, 0, 0), 90);
|
||||||
|
|
||||||
|
var _camera = params.camera;
|
||||||
|
var _qview = new BBMOD_Quaternion().FromEuler(_camera.focus_angle_y, -_camera.focus_angle_x, 0);
|
||||||
|
|
||||||
|
var _axis = tool_attribute.context;
|
||||||
|
|
||||||
|
var _hover = noone;
|
||||||
|
var _hoverDist = 10;
|
||||||
|
var th;
|
||||||
|
|
||||||
|
var _posView = _camera.worldPointToViewPoint(_vpos);
|
||||||
|
|
||||||
|
var cx = _posView.x;
|
||||||
|
var cy = _posView.y;
|
||||||
|
|
||||||
|
var ga = [];
|
||||||
|
var size = 64;
|
||||||
|
var hs = size / 2;
|
||||||
|
var sq = 8;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region display
|
||||||
|
var size = 64;
|
||||||
|
for( var i = 0; i < 3; i++ ) {
|
||||||
|
var op, np;
|
||||||
|
|
||||||
|
th = 2 + (axis_hover == i || drag_axis == i);
|
||||||
|
if(drag_axis != noone && drag_axis != i)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
draw_set_color(COLORS.axis[i]);
|
||||||
|
for( var j = 0; j <= 32; j++ ) {
|
||||||
|
var ang = j / 32 * 360;
|
||||||
|
|
||||||
|
switch(i) {
|
||||||
|
case 0 : np = new BBMOD_Vec3(0, lengthdir_x(size, ang), lengthdir_y(size, ang)); break;
|
||||||
|
case 1 : np = new BBMOD_Vec3(lengthdir_x(size, ang), lengthdir_y(size, ang), 0); break;
|
||||||
|
case 2 : np = new BBMOD_Vec3(lengthdir_x(size, ang), 0, lengthdir_y(size, ang)); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_axis == 0)
|
||||||
|
np = _qview.Rotate(_qinv.Rotate(_qrot.Rotate(np)));
|
||||||
|
else if(_axis == 1)
|
||||||
|
np = _qview.Rotate(_qinv.Rotate(np));
|
||||||
|
|
||||||
|
if(j && (op.Z > 0 && np.Z > 0 || drag_axis == i)) {
|
||||||
|
draw_line_round(cx + op.X, cy + op.Y, cx + np.X, cy + np.Y, th);
|
||||||
|
var _d = distance_to_line(_mx, _my, cx + op.X, cy + op.Y, cx + np.X, cy + np.Y);
|
||||||
|
if(_d < _hoverDist) {
|
||||||
|
_hover = i;
|
||||||
|
_hoverDist = _d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
op = np;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
axis_hover = _hover;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
if(drag_axis != noone) { #region
|
||||||
|
var mAng = point_direction(cx, cy, _mx, _my);
|
||||||
|
|
||||||
|
if(drag_rot_axis == undefined) {
|
||||||
|
drag_rot_axis = BBMOD_VEC3_FORWARD;
|
||||||
|
|
||||||
|
switch(drag_axis) {
|
||||||
|
case 0 : drag_rot_axis = new BBMOD_Vec3(-1, 0, 0); break;
|
||||||
|
case 1 : drag_rot_axis = new BBMOD_Vec3( 0, 0, -1); break;
|
||||||
|
case 2 : drag_rot_axis = new BBMOD_Vec3( 0, -1, 0); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_axis == 0) drag_rot_axis = _qrot.Rotate(drag_rot_axis).Normalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
var _nv = _qview.Rotate(_qinv.Rotate(drag_rot_axis));
|
||||||
|
draw_line_round(cx, cy, cx + _nv.X * 100, cy + _nv.Y * 100, 2);
|
||||||
|
|
||||||
|
if(drag_prev != undefined) {
|
||||||
|
var _rd = (mAng - drag_prev) * (_nv.Z > 0? 1 : -1);
|
||||||
|
drag_dist += _rd;
|
||||||
|
var _dist = value_snap(drag_dist, _sny);
|
||||||
|
|
||||||
|
var _currR = new BBMOD_Quaternion().FromAxisAngle(drag_rot_axis, _dist);
|
||||||
|
var _val = _currR.Mul(drag_val);
|
||||||
|
var _Nrot = _val.ToArray();
|
||||||
|
|
||||||
|
if(inputs[| index].setValue(_Nrot))
|
||||||
|
UNDO_HOLDING = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_set_color(COLORS._main_accent);
|
||||||
|
draw_line_dashed(cx, cy, _mx, _my, 1, 4);
|
||||||
|
|
||||||
|
drag_prev = mAng;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
if(_hover != noone && mouse_press(mb_left, active)) { #region
|
||||||
|
drag_axis = _hover;
|
||||||
|
drag_prev = undefined;
|
||||||
|
drag_val = _qrot.Clone();
|
||||||
|
drag_dist = 0;
|
||||||
|
|
||||||
|
drag_rot_axis = undefined;
|
||||||
|
} #endregion
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static drawGizmoScale = function(index, object, _vpos, active, params, _mx, _my, _snx, _sny, _panel) { #region
|
||||||
|
tool_attribute.context = 0;
|
||||||
|
#region ---- main ----
|
||||||
|
var _sca = inputs[| index].getValue(,,, true);
|
||||||
|
var _qrot = object == noone? new BBMOD_Quaternion() : object.transform.rotation;
|
||||||
|
var _qinv = new BBMOD_Quaternion().FromAxisAngle(new BBMOD_Vec3(1, 0, 0), 90);
|
||||||
|
|
||||||
|
var _camera = params.camera;
|
||||||
|
var _qview = new BBMOD_Quaternion().FromEuler(_camera.focus_angle_y, -_camera.focus_angle_x, 0);
|
||||||
|
|
||||||
|
var _axis = tool_attribute.context;
|
||||||
|
|
||||||
|
var _hover = noone;
|
||||||
|
var _hoverDist = 10;
|
||||||
|
var th;
|
||||||
|
|
||||||
|
var _posView = _camera.worldPointToViewPoint(_vpos);
|
||||||
|
|
||||||
|
var cx = _posView.x;
|
||||||
|
var cy = _posView.y;
|
||||||
|
|
||||||
|
var ga = [];
|
||||||
|
var size = 64;
|
||||||
|
var hs = size / 2;
|
||||||
|
var sq = 8;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region display
|
||||||
|
var ga = [];
|
||||||
|
var size = 64;
|
||||||
|
var hs = size / 2;
|
||||||
|
var sq = 8;
|
||||||
|
|
||||||
|
ga[0] = new BBMOD_Vec3(-size, 0, 0);
|
||||||
|
ga[1] = new BBMOD_Vec3(0, -size, 0);
|
||||||
|
ga[2] = new BBMOD_Vec3(0, 0, -size);
|
||||||
|
|
||||||
|
ga[3] = [ new BBMOD_Vec3(-hs + sq, -hs - sq, 0),
|
||||||
|
new BBMOD_Vec3(-hs - sq, -hs - sq, 0),
|
||||||
|
new BBMOD_Vec3(-hs - sq, -hs + sq, 0),
|
||||||
|
new BBMOD_Vec3(-hs + sq, -hs + sq, 0), ];
|
||||||
|
ga[4] = [ new BBMOD_Vec3( 0, -hs + sq, -hs - sq),
|
||||||
|
new BBMOD_Vec3( 0, -hs - sq, -hs - sq),
|
||||||
|
new BBMOD_Vec3( 0, -hs - sq, -hs + sq),
|
||||||
|
new BBMOD_Vec3( 0, -hs + sq, -hs + sq), ];
|
||||||
|
ga[5] = [ new BBMOD_Vec3(-hs + sq, 0, -hs - sq),
|
||||||
|
new BBMOD_Vec3(-hs - sq, 0, -hs - sq),
|
||||||
|
new BBMOD_Vec3(-hs - sq, 0, -hs + sq),
|
||||||
|
new BBMOD_Vec3(-hs + sq, 0, -hs + sq), ];
|
||||||
|
|
||||||
|
for( var i = 0; i < 3; i++ ) {
|
||||||
|
ga[i] = _qview.Rotate(_qinv.Rotate(_qrot.Rotate(ga[i])));
|
||||||
|
|
||||||
|
th = 2 + (axis_hover == i || drag_axis == i);
|
||||||
|
if(drag_axis != noone && drag_axis != i)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
draw_set_color(COLORS.axis[i]);
|
||||||
|
if(point_distance(cx, cy, cx + ga[i].X, cy + ga[i].Y) < 5)
|
||||||
|
draw_line_round(cx, cy, cx + ga[i].X, cy + ga[i].Y, th);
|
||||||
|
else
|
||||||
|
draw_line_round_arrow_block(cx, cy, cx + ga[i].X, cy + ga[i].Y, th, 3);
|
||||||
|
|
||||||
|
var _d = distance_to_line(_mx, _my, cx, cy, cx + ga[i].X, cy + ga[i].Y);
|
||||||
|
if(_d < _hoverDist) {
|
||||||
|
_hover = i;
|
||||||
|
_hoverDist = _d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( var i = 3; i < 6; i++ ) {
|
||||||
|
for( var j = 0; j < 4; j++ ) {
|
||||||
|
if(_axis == 0)
|
||||||
|
ga[i][j] = _qview.Rotate(_qinv.Rotate(_qrot.Rotate(ga[i][j])));
|
||||||
|
else
|
||||||
|
ga[i][j] = _qview.Rotate(_qinv.Rotate(ga[i][j]));
|
||||||
|
}
|
||||||
|
|
||||||
|
th = 1;
|
||||||
|
|
||||||
|
var p0x = cx + ga[i][0].X, p0y = cy + ga[i][0].Y;
|
||||||
|
var p1x = cx + ga[i][1].X, p1y = cy + ga[i][1].Y;
|
||||||
|
var p2x = cx + ga[i][2].X, p2y = cy + ga[i][2].Y;
|
||||||
|
var p3x = cx + ga[i][3].X, p3y = cy + ga[i][3].Y;
|
||||||
|
|
||||||
|
var _pax = (p0x + p1x + p2x + p3x) / 4;
|
||||||
|
var _pay = (p0y + p1y + p2y + p3y) / 4;
|
||||||
|
|
||||||
|
if((abs(p0x - _pax) + abs(p1x - _pax) + abs(p2x - _pax) + abs(p3x - _pax)) / 4 < 1)
|
||||||
|
continue;
|
||||||
|
if((abs(p0y - _pay) + abs(p1y - _pay) + abs(p2y - _pay) + abs(p3y - _pay)) / 4 < 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
draw_set_color(COLORS.axis[(i - 3 - 1 + 3) % 3]);
|
||||||
|
if(axis_hover == i || drag_axis == i) {
|
||||||
|
draw_primitive_begin(pr_trianglestrip);
|
||||||
|
draw_vertex(p0x, p0y);
|
||||||
|
draw_vertex(p1x, p1y);
|
||||||
|
draw_vertex(p3x, p3y);
|
||||||
|
draw_vertex(p2x, p2y);
|
||||||
|
draw_primitive_end();
|
||||||
|
} else if (drag_axis == noone) {
|
||||||
|
draw_line(p0x, p0y, p1x, p1y);
|
||||||
|
draw_line(p1x, p1y, p2x, p2y);
|
||||||
|
draw_line(p2x, p2y, p3x, p3y);
|
||||||
|
draw_line(p3x, p3y, p0x, p0y);
|
||||||
|
} else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(point_in_rectangle_points(_mx, _my, p0x, p0y, p1x, p1y, p3x, p3y, p2x, p2y))
|
||||||
|
_hover = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
axis_hover = _hover;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
if(drag_axis != noone) { #region editing
|
||||||
|
if(!MOUSE_WRAPPING) {
|
||||||
|
drag_mx += _mx - drag_px;
|
||||||
|
drag_my += _my - drag_py;
|
||||||
|
|
||||||
|
var mAdj, nor, prj;
|
||||||
|
var ray = _camera.viewPointToWorldRay(drag_mx, drag_my);
|
||||||
|
|
||||||
|
if(drag_axis < 3) {
|
||||||
|
switch(drag_axis) {
|
||||||
|
case 0 : nor = new __vec3(0, 1, 0); prj = new __vec3(1, 0, 0); break;
|
||||||
|
case 1 : nor = new __vec3(0, 0, 1); prj = new __vec3(0, 1, 0); break;
|
||||||
|
case 2 : nor = new __vec3(1, 0, 0); prj = new __vec3(0, 0, 1); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
nor = _qrot.Rotate(nor);
|
||||||
|
|
||||||
|
var pln = new __plane(drag_original, nor);
|
||||||
|
mAdj = d3d_intersect_ray_plane(ray, pln);
|
||||||
|
|
||||||
|
if(drag_prev != undefined) {
|
||||||
|
var _diff = mAdj.subtract(drag_prev);
|
||||||
|
var _dist = _diff.dot(prj);
|
||||||
|
|
||||||
|
drag_val[drag_axis] += prj.getIndex(drag_axis) * _dist;
|
||||||
|
|
||||||
|
if(inputs[| index].setValue(value_snap(drag_val, _snx)))
|
||||||
|
UNDO_HOLDING = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch(drag_axis) {
|
||||||
|
case 3 : nor = new __vec3(0, 0, 1); break;
|
||||||
|
case 4 : nor = new __vec3(1, 0, 0); break;
|
||||||
|
case 5 : nor = new __vec3(0, 1, 0); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
nor = _qrot.Rotate(nor);
|
||||||
|
|
||||||
|
var pln = new __plane(drag_original, nor);
|
||||||
|
mAdj = d3d_intersect_ray_plane(ray, pln);
|
||||||
|
|
||||||
|
if(drag_prev != undefined) {
|
||||||
|
var _diff = mAdj.subtract(drag_prev);
|
||||||
|
|
||||||
|
for( var i = 0; i < 3; i++ )
|
||||||
|
drag_val[i] += _diff.getIndex(i);
|
||||||
|
|
||||||
|
if(inputs[| index].setValue(value_snap(drag_val, _snx)))
|
||||||
|
UNDO_HOLDING = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drag_prev = mAdj;
|
||||||
|
}
|
||||||
|
|
||||||
|
setMouseWrap();
|
||||||
|
drag_px = _mx;
|
||||||
|
drag_py = _my;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
if(_hover != noone && mouse_press(mb_left, active)) { #region
|
||||||
|
drag_axis = _hover;
|
||||||
|
drag_prev = undefined;
|
||||||
|
drag_mx = _mx;
|
||||||
|
drag_my = _my;
|
||||||
|
drag_px = _mx;
|
||||||
|
drag_py = _my;
|
||||||
|
drag_cx = cx;
|
||||||
|
drag_cy = cy;
|
||||||
|
|
||||||
|
drag_val = [ _sca[0], _sca[1], _sca[2] ];
|
||||||
|
drag_original = new __vec3(_sca);
|
||||||
|
} #endregion
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static drawOverlay3D = function(active, params, _mx, _my, _snx, _sny, _panel) { #region
|
||||||
|
var object = getPreviewObjects();
|
||||||
|
if(array_empty(object)) return;
|
||||||
|
object = object[0];
|
||||||
|
|
||||||
|
var _pos = inputs[| 0].getValue(,,, true);
|
||||||
|
var _vpos = new __vec3( _pos[0], _pos[1], _pos[2] );
|
||||||
|
|
||||||
|
if(isUsingTool("Transform")) drawGizmoPosition(0, object, _vpos, active, params, _mx, _my, _snx, _sny, _panel);
|
||||||
|
else if(isUsingTool("Rotate")) drawGizmoRotation(1, object, _vpos, active, params, _mx, _my, _snx, _sny, _panel);
|
||||||
|
else if(isUsingTool("Scale")) drawGizmoScale(2, object, _vpos, active, params, _mx, _my, _snx, _sny, _panel);
|
||||||
|
|
||||||
|
if(drag_axis != noone && mouse_release(mb_left)) {
|
||||||
|
drag_axis = noone;
|
||||||
|
UNDO_HOLDING = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(onDrawOverlay3D != 0) onDrawOverlay3D(active, params, _mx, _my, _snx, _sny, _panel);
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static onDrawOverlay3D = 0;
|
||||||
|
|
||||||
|
static setTransform = function(object, _data) { #region
|
||||||
|
if(object == noone) return;
|
||||||
|
var _pos = _data[0];
|
||||||
|
var _rot = _data[1];
|
||||||
|
var _sca = _data[2];
|
||||||
|
var _anc = _data[3];
|
||||||
|
|
||||||
|
object.transform.position.set( _pos[0], _pos[1], _pos[2]);
|
||||||
|
object.transform.anchor.set( _anc[0], _anc[1], _anc[2]);
|
||||||
|
object.transform.rotation.set( _rot[0], _rot[1], _rot[2], _rot[3]);
|
||||||
|
object.transform.scale.set( _sca[0], _sca[1], _sca[2]);
|
||||||
|
|
||||||
|
return object;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static getObject = function(index, class = object_class) { #region
|
||||||
|
var _obj = array_safe_get_fast(cached_object, index, noone);
|
||||||
|
if(_obj == noone) {
|
||||||
|
_obj = new class();
|
||||||
|
} else if(!is_instanceof(_obj, class)) {
|
||||||
|
_obj.destroy();
|
||||||
|
_obj = new class();
|
||||||
|
}
|
||||||
|
|
||||||
|
cached_object[index] = _obj;
|
||||||
|
return _obj;
|
||||||
|
} #endregion
|
||||||
|
}
|
633
#backups/scripts/__node_3d_object/__node_3d_object.gml.backup1
Normal file
633
#backups/scripts/__node_3d_object/__node_3d_object.gml.backup1
Normal file
|
@ -0,0 +1,633 @@
|
||||||
|
// 2024-05-01 16:28:38
|
||||||
|
function Node_3D_Object(_x, _y, _group = noone) : Node_3D(_x, _y, _group) constructor {
|
||||||
|
name = "3D Object";
|
||||||
|
cached_object = [];
|
||||||
|
object_class = noone;
|
||||||
|
|
||||||
|
preview_channel = 0;
|
||||||
|
|
||||||
|
inputs[| 0] = nodeValue("Position", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0, 0 ])
|
||||||
|
.setDisplay(VALUE_DISPLAY.vector);
|
||||||
|
|
||||||
|
inputs[| 1] = nodeValue("Rotation", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0, 0, 1 ])
|
||||||
|
.setDisplay(VALUE_DISPLAY.d3quarternion);
|
||||||
|
|
||||||
|
inputs[| 2] = nodeValue("Scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 1, 1, 1 ])
|
||||||
|
.setDisplay(VALUE_DISPLAY.vector);
|
||||||
|
|
||||||
|
inputs[| 3] = nodeValue("Anchor", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0, 0 ])
|
||||||
|
.setDisplay(VALUE_DISPLAY.vector);
|
||||||
|
|
||||||
|
in_d3d = ds_list_size(inputs);
|
||||||
|
|
||||||
|
#macro __d3d_input_list_transform ["Transform", false], 0, 3, 1, 2
|
||||||
|
|
||||||
|
#region ---- overlay ----
|
||||||
|
drag_axis = noone;
|
||||||
|
drag_sv = 0;
|
||||||
|
drag_delta = 0;
|
||||||
|
drag_prev = 0;
|
||||||
|
drag_dist = 0;
|
||||||
|
drag_val = 0;
|
||||||
|
|
||||||
|
drag_mx = 0;
|
||||||
|
drag_my = 0;
|
||||||
|
drag_px = 0;
|
||||||
|
drag_py = 0;
|
||||||
|
drag_cx = 0;
|
||||||
|
drag_cy = 0;
|
||||||
|
drag_rot_axis = new BBMOD_Quaternion();
|
||||||
|
|
||||||
|
drag_original = 0;
|
||||||
|
|
||||||
|
axis_hover = noone;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ---- tools ----
|
||||||
|
tool_pos = new NodeTool( "Transform", THEME.tools_3d_transform, "Node_3D_Object" );
|
||||||
|
tool_rot = new NodeTool( "Rotate", THEME.tools_3d_rotate, "Node_3D_Object" );
|
||||||
|
tool_sca = new NodeTool( "Scale", THEME.tools_3d_scale, "Node_3D_Object" );
|
||||||
|
tools = [ tool_pos, tool_rot, tool_sca ];
|
||||||
|
|
||||||
|
tool_axis_edit = new scrollBox([ "local", "global" ], function(val) { tool_attribute.context = val; });
|
||||||
|
// tool_axis_edit.font = f_p2;
|
||||||
|
// tool_axis_edit.arrow_spr = THEME.arrow;
|
||||||
|
// tool_axis_edit.arrow_ind = 3;
|
||||||
|
tool_attribute.context = 0;
|
||||||
|
tool_settings = [
|
||||||
|
[ "Axis", tool_axis_edit, "context", tool_attribute ],
|
||||||
|
];
|
||||||
|
|
||||||
|
static getToolSettings = function() {
|
||||||
|
if(isUsingTool("Transform") || isUsingTool("Rotate"))
|
||||||
|
return tool_settings;
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
static drawGizmoPosition = function(index, object, _vpos, active, params, _mx, _my, _snx, _sny, _panel) { #region
|
||||||
|
#region ---- main ----
|
||||||
|
var _pos = inputs[| index].getValue(,,, true);
|
||||||
|
var _qrot = object == noone? new BBMOD_Quaternion() : object.transform.rotation;
|
||||||
|
var _qinv = new BBMOD_Quaternion().FromAxisAngle(new BBMOD_Vec3(1, 0, 0), 90);
|
||||||
|
|
||||||
|
var _camera = params.camera;
|
||||||
|
var _qview = new BBMOD_Quaternion().FromEuler(_camera.focus_angle_y, -_camera.focus_angle_x, 0);
|
||||||
|
|
||||||
|
var _axis = tool_attribute.context;
|
||||||
|
|
||||||
|
var _hover = noone;
|
||||||
|
var _hoverDist = 10;
|
||||||
|
var th;
|
||||||
|
|
||||||
|
var _posView = _camera.worldPointToViewPoint(_vpos);
|
||||||
|
|
||||||
|
var cx = _posView.x;
|
||||||
|
var cy = _posView.y;
|
||||||
|
|
||||||
|
var ga = [];
|
||||||
|
var size = 64;
|
||||||
|
var hs = size / 2;
|
||||||
|
var sq = 8;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region display
|
||||||
|
ga[0] = new BBMOD_Vec3(-size, 0, 0);
|
||||||
|
ga[1] = new BBMOD_Vec3(0, 0, size);
|
||||||
|
ga[2] = new BBMOD_Vec3(0, -size, 0);
|
||||||
|
|
||||||
|
ga[3] = [ new BBMOD_Vec3(-hs + sq, 0, hs - sq),
|
||||||
|
new BBMOD_Vec3(-hs - sq, 0, hs - sq),
|
||||||
|
new BBMOD_Vec3(-hs - sq, 0, hs + sq),
|
||||||
|
new BBMOD_Vec3(-hs + sq, 0, hs + sq), ];
|
||||||
|
ga[4] = [ new BBMOD_Vec3( 0, -hs + sq, hs - sq),
|
||||||
|
new BBMOD_Vec3( 0, -hs - sq, hs - sq),
|
||||||
|
new BBMOD_Vec3( 0, -hs - sq, hs + sq),
|
||||||
|
new BBMOD_Vec3( 0, -hs + sq, hs + sq), ];
|
||||||
|
ga[5] = [ new BBMOD_Vec3(-hs + sq, -hs - sq, 0),
|
||||||
|
new BBMOD_Vec3(-hs - sq, -hs - sq, 0),
|
||||||
|
new BBMOD_Vec3(-hs - sq, -hs + sq, 0),
|
||||||
|
new BBMOD_Vec3(-hs + sq, -hs + sq, 0), ];
|
||||||
|
|
||||||
|
ga[0] = new BBMOD_Vec3(-size, 0, 0);
|
||||||
|
ga[1] = new BBMOD_Vec3(0, -size, 0);
|
||||||
|
ga[2] = new BBMOD_Vec3(0, 0, -size);
|
||||||
|
|
||||||
|
ga[3] = [ new BBMOD_Vec3(-hs + sq, -hs - sq, 0),
|
||||||
|
new BBMOD_Vec3(-hs - sq, -hs - sq, 0),
|
||||||
|
new BBMOD_Vec3(-hs - sq, -hs + sq, 0),
|
||||||
|
new BBMOD_Vec3(-hs + sq, -hs + sq, 0), ];
|
||||||
|
ga[4] = [ new BBMOD_Vec3( 0, -hs + sq, -hs - sq),
|
||||||
|
new BBMOD_Vec3( 0, -hs - sq, -hs - sq),
|
||||||
|
new BBMOD_Vec3( 0, -hs - sq, -hs + sq),
|
||||||
|
new BBMOD_Vec3( 0, -hs + sq, -hs + sq), ];
|
||||||
|
ga[5] = [ new BBMOD_Vec3(-hs + sq, 0, -hs - sq),
|
||||||
|
new BBMOD_Vec3(-hs - sq, 0, -hs - sq),
|
||||||
|
new BBMOD_Vec3(-hs - sq, 0, -hs + sq),
|
||||||
|
new BBMOD_Vec3(-hs + sq, 0, -hs + sq), ];
|
||||||
|
|
||||||
|
for( var i = 0; i < 3; i++ ) {
|
||||||
|
if(_axis == 0)
|
||||||
|
ga[i] = _qview.Rotate(_qinv.Rotate(_qrot.Rotate(ga[i])));
|
||||||
|
else if(_axis == 1)
|
||||||
|
ga[i] = _qview.Rotate(_qinv.Rotate(ga[i]));
|
||||||
|
|
||||||
|
th = 2 + (axis_hover == i || drag_axis == i);
|
||||||
|
if(drag_axis != noone && drag_axis != i)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
draw_set_color(COLORS.axis[i]);
|
||||||
|
if(point_distance(cx, cy, cx + ga[i].X, cy + ga[i].Y) < 5)
|
||||||
|
draw_line_round(cx, cy, cx + ga[i].X, cy + ga[i].Y, th);
|
||||||
|
else
|
||||||
|
draw_line_round_arrow(cx, cy, cx + ga[i].X, cy + ga[i].Y, th, 3);
|
||||||
|
|
||||||
|
var _d = distance_to_line(_mx, _my, cx, cy, cx + ga[i].X, cy + ga[i].Y);
|
||||||
|
if(_d < _hoverDist) {
|
||||||
|
_hover = i;
|
||||||
|
_hoverDist = _d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( var i = 3; i < 6; i++ ) {
|
||||||
|
for( var j = 0; j < 4; j++ ) {
|
||||||
|
if(_axis == 0)
|
||||||
|
ga[i][j] = _qview.Rotate(_qinv.Rotate(_qrot.Rotate(ga[i][j])));
|
||||||
|
else if(_axis == 1)
|
||||||
|
ga[i][j] = _qview.Rotate(_qinv.Rotate(ga[i][j]));
|
||||||
|
}
|
||||||
|
|
||||||
|
th = 1;
|
||||||
|
|
||||||
|
var p0x = cx + ga[i][0].X, p0y = cy + ga[i][0].Y;
|
||||||
|
var p1x = cx + ga[i][1].X, p1y = cy + ga[i][1].Y;
|
||||||
|
var p2x = cx + ga[i][2].X, p2y = cy + ga[i][2].Y;
|
||||||
|
var p3x = cx + ga[i][3].X, p3y = cy + ga[i][3].Y;
|
||||||
|
|
||||||
|
var _pax = (p0x + p1x + p2x + p3x) / 4;
|
||||||
|
var _pay = (p0y + p1y + p2y + p3y) / 4;
|
||||||
|
|
||||||
|
if((abs(p0x - _pax) + abs(p1x - _pax) + abs(p2x - _pax) + abs(p3x - _pax)) / 4 < 1)
|
||||||
|
continue;
|
||||||
|
if((abs(p0y - _pay) + abs(p1y - _pay) + abs(p2y - _pay) + abs(p3y - _pay)) / 4 < 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
draw_set_color(COLORS.axis[(i - 3 - 1 + 3) % 3]);
|
||||||
|
if(axis_hover == i || drag_axis == i) {
|
||||||
|
draw_primitive_begin(pr_trianglestrip);
|
||||||
|
draw_vertex(p0x, p0y);
|
||||||
|
draw_vertex(p1x, p1y);
|
||||||
|
draw_vertex(p3x, p3y);
|
||||||
|
draw_vertex(p2x, p2y);
|
||||||
|
draw_primitive_end();
|
||||||
|
} else if (drag_axis == noone) {
|
||||||
|
draw_line(p0x, p0y, p1x, p1y);
|
||||||
|
draw_line(p1x, p1y, p2x, p2y);
|
||||||
|
draw_line(p2x, p2y, p3x, p3y);
|
||||||
|
draw_line(p3x, p3y, p0x, p0y);
|
||||||
|
} else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(point_in_rectangle_points(_mx, _my, p0x, p0y, p1x, p1y, p3x, p3y, p2x, p2y))
|
||||||
|
_hover = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
axis_hover = _hover;
|
||||||
|
#endregion display
|
||||||
|
|
||||||
|
if(drag_axis != noone) { #region editing
|
||||||
|
if(!MOUSE_WRAPPING) {
|
||||||
|
drag_mx += _mx - drag_px;
|
||||||
|
drag_my += _my - drag_py;
|
||||||
|
|
||||||
|
var mAdj, nor, prj;
|
||||||
|
|
||||||
|
var ray = _camera.viewPointToWorldRay(drag_mx, drag_my);
|
||||||
|
var val = [ drag_val[0], drag_val[1], drag_val[2] ];
|
||||||
|
|
||||||
|
if(drag_axis < 3) {
|
||||||
|
switch(drag_axis) {
|
||||||
|
case 0 : nor = new __vec3(0, 1, 0); prj = new __vec3(1, 0, 0); break;
|
||||||
|
case 1 : nor = new __vec3(0, 0, 1); prj = new __vec3(0, 1, 0); break;
|
||||||
|
case 2 : nor = new __vec3(1, 0, 0); prj = new __vec3(0, 0, 1); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_axis == 0) {
|
||||||
|
nor = _qrot.Rotate(nor);
|
||||||
|
prj = _qrot.Rotate(prj);
|
||||||
|
}
|
||||||
|
|
||||||
|
var pln = new __plane(drag_original, nor);
|
||||||
|
mAdj = d3d_intersect_ray_plane(ray, pln);
|
||||||
|
|
||||||
|
if(drag_prev != undefined) {
|
||||||
|
var _diff = mAdj.subtract(drag_prev);
|
||||||
|
var _dist = _diff.dot(prj);
|
||||||
|
|
||||||
|
for( var i = 0; i < 3; i++ )
|
||||||
|
val[i] += prj.getIndex(i) * _dist;
|
||||||
|
|
||||||
|
if(inputs[| index].setValue(value_snap(val, _snx)))
|
||||||
|
UNDO_HOLDING = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch(drag_axis) {
|
||||||
|
case 3 : nor = new __vec3(0, 0, 1); break;
|
||||||
|
case 4 : nor = new __vec3(1, 0, 0); break;
|
||||||
|
case 5 : nor = new __vec3(0, 1, 0); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_axis == 0)
|
||||||
|
nor = _qrot.Rotate(nor);
|
||||||
|
|
||||||
|
var pln = new __plane(drag_original, nor);
|
||||||
|
mAdj = d3d_intersect_ray_plane(ray, pln);
|
||||||
|
|
||||||
|
if(drag_prev != undefined) {
|
||||||
|
var _diff = mAdj.subtract(drag_prev);
|
||||||
|
|
||||||
|
for( var i = 0; i < 3; i++ )
|
||||||
|
val[i] += _diff.getIndex(i);
|
||||||
|
|
||||||
|
if(inputs[| index].setValue(value_snap(val, _snx)))
|
||||||
|
UNDO_HOLDING = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drag_val = [ val[0], val[1], val[2] ];
|
||||||
|
drag_prev = mAdj;
|
||||||
|
}
|
||||||
|
|
||||||
|
setMouseWrap();
|
||||||
|
drag_px = _mx;
|
||||||
|
drag_py = _my;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
if(_hover != noone && mouse_press(mb_left, active)) { #region
|
||||||
|
drag_axis = _hover;
|
||||||
|
drag_prev = undefined;
|
||||||
|
drag_mx = _mx;
|
||||||
|
drag_my = _my;
|
||||||
|
drag_px = _mx;
|
||||||
|
drag_py = _my;
|
||||||
|
drag_cx = cx;
|
||||||
|
drag_cy = cy;
|
||||||
|
|
||||||
|
drag_val = _pos;
|
||||||
|
drag_original = new __vec3(_pos);
|
||||||
|
} #endregion
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static drawGizmoRotation = function(index, object, _vpos, active, params, _mx, _my, _snx, _sny, _panel) { #region
|
||||||
|
#region ---- main ----
|
||||||
|
var _rot = inputs[| index].getValue();
|
||||||
|
var _qrot = object == noone? new BBMOD_Quaternion() : object.transform.rotation;
|
||||||
|
var _qinv = new BBMOD_Quaternion().FromAxisAngle(new BBMOD_Vec3(1, 0, 0), 90);
|
||||||
|
|
||||||
|
var _camera = params.camera;
|
||||||
|
var _qview = new BBMOD_Quaternion().FromEuler(_camera.focus_angle_y, -_camera.focus_angle_x, 0);
|
||||||
|
|
||||||
|
var _axis = tool_attribute.context;
|
||||||
|
|
||||||
|
var _hover = noone;
|
||||||
|
var _hoverDist = 10;
|
||||||
|
var th;
|
||||||
|
|
||||||
|
var _posView = _camera.worldPointToViewPoint(_vpos);
|
||||||
|
|
||||||
|
var cx = _posView.x;
|
||||||
|
var cy = _posView.y;
|
||||||
|
|
||||||
|
var ga = [];
|
||||||
|
var size = 64;
|
||||||
|
var hs = size / 2;
|
||||||
|
var sq = 8;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region display
|
||||||
|
var size = 64;
|
||||||
|
for( var i = 0; i < 3; i++ ) {
|
||||||
|
var op, np;
|
||||||
|
|
||||||
|
th = 2 + (axis_hover == i || drag_axis == i);
|
||||||
|
if(drag_axis != noone && drag_axis != i)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
draw_set_color(COLORS.axis[i]);
|
||||||
|
for( var j = 0; j <= 32; j++ ) {
|
||||||
|
var ang = j / 32 * 360;
|
||||||
|
|
||||||
|
switch(i) {
|
||||||
|
case 0 : np = new BBMOD_Vec3(0, lengthdir_x(size, ang), lengthdir_y(size, ang)); break;
|
||||||
|
case 1 : np = new BBMOD_Vec3(lengthdir_x(size, ang), lengthdir_y(size, ang), 0); break;
|
||||||
|
case 2 : np = new BBMOD_Vec3(lengthdir_x(size, ang), 0, lengthdir_y(size, ang)); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_axis == 0)
|
||||||
|
np = _qview.Rotate(_qinv.Rotate(_qrot.Rotate(np)));
|
||||||
|
else if(_axis == 1)
|
||||||
|
np = _qview.Rotate(_qinv.Rotate(np));
|
||||||
|
|
||||||
|
if(j && (op.Z > 0 && np.Z > 0 || drag_axis == i)) {
|
||||||
|
draw_line_round(cx + op.X, cy + op.Y, cx + np.X, cy + np.Y, th);
|
||||||
|
var _d = distance_to_line(_mx, _my, cx + op.X, cy + op.Y, cx + np.X, cy + np.Y);
|
||||||
|
if(_d < _hoverDist) {
|
||||||
|
_hover = i;
|
||||||
|
_hoverDist = _d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
op = np;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
axis_hover = _hover;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
if(drag_axis != noone) { #region
|
||||||
|
var mAng = point_direction(cx, cy, _mx, _my);
|
||||||
|
|
||||||
|
if(drag_rot_axis == undefined) {
|
||||||
|
drag_rot_axis = BBMOD_VEC3_FORWARD;
|
||||||
|
|
||||||
|
switch(drag_axis) {
|
||||||
|
case 0 : drag_rot_axis = new BBMOD_Vec3(-1, 0, 0); break;
|
||||||
|
case 1 : drag_rot_axis = new BBMOD_Vec3( 0, 0, -1); break;
|
||||||
|
case 2 : drag_rot_axis = new BBMOD_Vec3( 0, -1, 0); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_axis == 0) drag_rot_axis = _qrot.Rotate(drag_rot_axis).Normalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
var _nv = _qview.Rotate(_qinv.Rotate(drag_rot_axis));
|
||||||
|
draw_line_round(cx, cy, cx + _nv.X * 100, cy + _nv.Y * 100, 2);
|
||||||
|
|
||||||
|
if(drag_prev != undefined) {
|
||||||
|
var _rd = (mAng - drag_prev) * (_nv.Z > 0? 1 : -1);
|
||||||
|
drag_dist += _rd;
|
||||||
|
var _dist = value_snap(drag_dist, _sny);
|
||||||
|
|
||||||
|
var _currR = new BBMOD_Quaternion().FromAxisAngle(drag_rot_axis, _dist);
|
||||||
|
var _val = _currR.Mul(drag_val);
|
||||||
|
var _Nrot = _val.ToArray();
|
||||||
|
|
||||||
|
if(inputs[| index].setValue(_Nrot))
|
||||||
|
UNDO_HOLDING = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_set_color(COLORS._main_accent);
|
||||||
|
draw_line_dashed(cx, cy, _mx, _my, 1, 4);
|
||||||
|
|
||||||
|
drag_prev = mAng;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
if(_hover != noone && mouse_press(mb_left, active)) { #region
|
||||||
|
drag_axis = _hover;
|
||||||
|
drag_prev = undefined;
|
||||||
|
drag_val = _qrot.Clone();
|
||||||
|
drag_dist = 0;
|
||||||
|
|
||||||
|
drag_rot_axis = undefined;
|
||||||
|
} #endregion
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static drawGizmoScale = function(index, object, _vpos, active, params, _mx, _my, _snx, _sny, _panel) { #region
|
||||||
|
tool_attribute.context = 0;
|
||||||
|
#region ---- main ----
|
||||||
|
var _sca = inputs[| index].getValue(,,, true);
|
||||||
|
var _qrot = object == noone? new BBMOD_Quaternion() : object.transform.rotation;
|
||||||
|
var _qinv = new BBMOD_Quaternion().FromAxisAngle(new BBMOD_Vec3(1, 0, 0), 90);
|
||||||
|
|
||||||
|
var _camera = params.camera;
|
||||||
|
var _qview = new BBMOD_Quaternion().FromEuler(_camera.focus_angle_y, -_camera.focus_angle_x, 0);
|
||||||
|
|
||||||
|
var _axis = tool_attribute.context;
|
||||||
|
|
||||||
|
var _hover = noone;
|
||||||
|
var _hoverDist = 10;
|
||||||
|
var th;
|
||||||
|
|
||||||
|
var _posView = _camera.worldPointToViewPoint(_vpos);
|
||||||
|
|
||||||
|
var cx = _posView.x;
|
||||||
|
var cy = _posView.y;
|
||||||
|
|
||||||
|
var ga = [];
|
||||||
|
var size = 64;
|
||||||
|
var hs = size / 2;
|
||||||
|
var sq = 8;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region display
|
||||||
|
var ga = [];
|
||||||
|
var size = 64;
|
||||||
|
var hs = size / 2;
|
||||||
|
var sq = 8;
|
||||||
|
|
||||||
|
ga[0] = new BBMOD_Vec3(-size, 0, 0);
|
||||||
|
ga[1] = new BBMOD_Vec3(0, -size, 0);
|
||||||
|
ga[2] = new BBMOD_Vec3(0, 0, -size);
|
||||||
|
|
||||||
|
ga[3] = [ new BBMOD_Vec3(-hs + sq, -hs - sq, 0),
|
||||||
|
new BBMOD_Vec3(-hs - sq, -hs - sq, 0),
|
||||||
|
new BBMOD_Vec3(-hs - sq, -hs + sq, 0),
|
||||||
|
new BBMOD_Vec3(-hs + sq, -hs + sq, 0), ];
|
||||||
|
ga[4] = [ new BBMOD_Vec3( 0, -hs + sq, -hs - sq),
|
||||||
|
new BBMOD_Vec3( 0, -hs - sq, -hs - sq),
|
||||||
|
new BBMOD_Vec3( 0, -hs - sq, -hs + sq),
|
||||||
|
new BBMOD_Vec3( 0, -hs + sq, -hs + sq), ];
|
||||||
|
ga[5] = [ new BBMOD_Vec3(-hs + sq, 0, -hs - sq),
|
||||||
|
new BBMOD_Vec3(-hs - sq, 0, -hs - sq),
|
||||||
|
new BBMOD_Vec3(-hs - sq, 0, -hs + sq),
|
||||||
|
new BBMOD_Vec3(-hs + sq, 0, -hs + sq), ];
|
||||||
|
|
||||||
|
for( var i = 0; i < 3; i++ ) {
|
||||||
|
ga[i] = _qview.Rotate(_qinv.Rotate(_qrot.Rotate(ga[i])));
|
||||||
|
|
||||||
|
th = 2 + (axis_hover == i || drag_axis == i);
|
||||||
|
if(drag_axis != noone && drag_axis != i)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
draw_set_color(COLORS.axis[i]);
|
||||||
|
if(point_distance(cx, cy, cx + ga[i].X, cy + ga[i].Y) < 5)
|
||||||
|
draw_line_round(cx, cy, cx + ga[i].X, cy + ga[i].Y, th);
|
||||||
|
else
|
||||||
|
draw_line_round_arrow_block(cx, cy, cx + ga[i].X, cy + ga[i].Y, th, 3);
|
||||||
|
|
||||||
|
var _d = distance_to_line(_mx, _my, cx, cy, cx + ga[i].X, cy + ga[i].Y);
|
||||||
|
if(_d < _hoverDist) {
|
||||||
|
_hover = i;
|
||||||
|
_hoverDist = _d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( var i = 3; i < 6; i++ ) {
|
||||||
|
for( var j = 0; j < 4; j++ ) {
|
||||||
|
if(_axis == 0)
|
||||||
|
ga[i][j] = _qview.Rotate(_qinv.Rotate(_qrot.Rotate(ga[i][j])));
|
||||||
|
else
|
||||||
|
ga[i][j] = _qview.Rotate(_qinv.Rotate(ga[i][j]));
|
||||||
|
}
|
||||||
|
|
||||||
|
th = 1;
|
||||||
|
|
||||||
|
var p0x = cx + ga[i][0].X, p0y = cy + ga[i][0].Y;
|
||||||
|
var p1x = cx + ga[i][1].X, p1y = cy + ga[i][1].Y;
|
||||||
|
var p2x = cx + ga[i][2].X, p2y = cy + ga[i][2].Y;
|
||||||
|
var p3x = cx + ga[i][3].X, p3y = cy + ga[i][3].Y;
|
||||||
|
|
||||||
|
var _pax = (p0x + p1x + p2x + p3x) / 4;
|
||||||
|
var _pay = (p0y + p1y + p2y + p3y) / 4;
|
||||||
|
|
||||||
|
if((abs(p0x - _pax) + abs(p1x - _pax) + abs(p2x - _pax) + abs(p3x - _pax)) / 4 < 1)
|
||||||
|
continue;
|
||||||
|
if((abs(p0y - _pay) + abs(p1y - _pay) + abs(p2y - _pay) + abs(p3y - _pay)) / 4 < 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
draw_set_color(COLORS.axis[(i - 3 - 1 + 3) % 3]);
|
||||||
|
if(axis_hover == i || drag_axis == i) {
|
||||||
|
draw_primitive_begin(pr_trianglestrip);
|
||||||
|
draw_vertex(p0x, p0y);
|
||||||
|
draw_vertex(p1x, p1y);
|
||||||
|
draw_vertex(p3x, p3y);
|
||||||
|
draw_vertex(p2x, p2y);
|
||||||
|
draw_primitive_end();
|
||||||
|
} else if (drag_axis == noone) {
|
||||||
|
draw_line(p0x, p0y, p1x, p1y);
|
||||||
|
draw_line(p1x, p1y, p2x, p2y);
|
||||||
|
draw_line(p2x, p2y, p3x, p3y);
|
||||||
|
draw_line(p3x, p3y, p0x, p0y);
|
||||||
|
} else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(point_in_rectangle_points(_mx, _my, p0x, p0y, p1x, p1y, p3x, p3y, p2x, p2y))
|
||||||
|
_hover = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
axis_hover = _hover;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
if(drag_axis != noone) { #region editing
|
||||||
|
if(!MOUSE_WRAPPING) {
|
||||||
|
drag_mx += _mx - drag_px;
|
||||||
|
drag_my += _my - drag_py;
|
||||||
|
|
||||||
|
var mAdj, nor, prj;
|
||||||
|
var ray = _camera.viewPointToWorldRay(drag_mx, drag_my);
|
||||||
|
|
||||||
|
if(drag_axis < 3) {
|
||||||
|
switch(drag_axis) {
|
||||||
|
case 0 : nor = new __vec3(0, 1, 0); prj = new __vec3(1, 0, 0); break;
|
||||||
|
case 1 : nor = new __vec3(0, 0, 1); prj = new __vec3(0, 1, 0); break;
|
||||||
|
case 2 : nor = new __vec3(1, 0, 0); prj = new __vec3(0, 0, 1); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
nor = _qrot.Rotate(nor);
|
||||||
|
|
||||||
|
var pln = new __plane(drag_original, nor);
|
||||||
|
mAdj = d3d_intersect_ray_plane(ray, pln);
|
||||||
|
|
||||||
|
if(drag_prev != undefined) {
|
||||||
|
var _diff = mAdj.subtract(drag_prev);
|
||||||
|
var _dist = _diff.dot(prj);
|
||||||
|
|
||||||
|
drag_val[drag_axis] += prj.getIndex(drag_axis) * _dist;
|
||||||
|
|
||||||
|
if(inputs[| index].setValue(value_snap(drag_val, _snx)))
|
||||||
|
UNDO_HOLDING = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch(drag_axis) {
|
||||||
|
case 3 : nor = new __vec3(0, 0, 1); break;
|
||||||
|
case 4 : nor = new __vec3(1, 0, 0); break;
|
||||||
|
case 5 : nor = new __vec3(0, 1, 0); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
nor = _qrot.Rotate(nor);
|
||||||
|
|
||||||
|
var pln = new __plane(drag_original, nor);
|
||||||
|
mAdj = d3d_intersect_ray_plane(ray, pln);
|
||||||
|
|
||||||
|
if(drag_prev != undefined) {
|
||||||
|
var _diff = mAdj.subtract(drag_prev);
|
||||||
|
|
||||||
|
for( var i = 0; i < 3; i++ )
|
||||||
|
drag_val[i] += _diff.getIndex(i);
|
||||||
|
|
||||||
|
if(inputs[| index].setValue(value_snap(drag_val, _snx)))
|
||||||
|
UNDO_HOLDING = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drag_prev = mAdj;
|
||||||
|
}
|
||||||
|
|
||||||
|
setMouseWrap();
|
||||||
|
drag_px = _mx;
|
||||||
|
drag_py = _my;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
if(_hover != noone && mouse_press(mb_left, active)) { #region
|
||||||
|
drag_axis = _hover;
|
||||||
|
drag_prev = undefined;
|
||||||
|
drag_mx = _mx;
|
||||||
|
drag_my = _my;
|
||||||
|
drag_px = _mx;
|
||||||
|
drag_py = _my;
|
||||||
|
drag_cx = cx;
|
||||||
|
drag_cy = cy;
|
||||||
|
|
||||||
|
drag_val = [ _sca[0], _sca[1], _sca[2] ];
|
||||||
|
drag_original = new __vec3(_sca);
|
||||||
|
} #endregion
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static drawOverlay3D = function(active, params, _mx, _my, _snx, _sny, _panel) { #region
|
||||||
|
var object = getPreviewObjects();
|
||||||
|
if(array_empty(object)) return;
|
||||||
|
object = object[0];
|
||||||
|
|
||||||
|
var _pos = inputs[| 0].getValue(,,, true);
|
||||||
|
var _vpos = new __vec3( _pos[0], _pos[1], _pos[2] );
|
||||||
|
|
||||||
|
if(isUsingTool("Transform")) drawGizmoPosition(0, object, _vpos, active, params, _mx, _my, _snx, _sny, _panel);
|
||||||
|
else if(isUsingTool("Rotate")) drawGizmoRotation(1, object, _vpos, active, params, _mx, _my, _snx, _sny, _panel);
|
||||||
|
else if(isUsingTool("Scale")) drawGizmoScale(2, object, _vpos, active, params, _mx, _my, _snx, _sny, _panel);
|
||||||
|
|
||||||
|
if(drag_axis != noone && mouse_release(mb_left)) {
|
||||||
|
drag_axis = noone;
|
||||||
|
UNDO_HOLDING = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(onDrawOverlay3D != 0) onDrawOverlay3D(active, params, _mx, _my, _snx, _sny, _panel);
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static onDrawOverlay3D = 0;
|
||||||
|
|
||||||
|
static setTransform = function(object, _data) { #region
|
||||||
|
if(object == noone) return;
|
||||||
|
var _pos = _data[0];
|
||||||
|
var _rot = _data[1];
|
||||||
|
var _sca = _data[2];
|
||||||
|
var _anc = _data[3];
|
||||||
|
|
||||||
|
object.transform.position.set( _pos[0], _pos[1], _pos[2]);
|
||||||
|
object.transform.anchor.set( _anc[0], _anc[1], _anc[2]);
|
||||||
|
object.transform.rotation.set( _rot[0], _rot[1], _rot[2], _rot[3]);
|
||||||
|
object.transform.scale.set( _sca[0], _sca[1], _sca[2]);
|
||||||
|
|
||||||
|
return object;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static getObject = function(index, class = object_class) { #region
|
||||||
|
var _obj = array_safe_get_fast(cached_object, index, noone);
|
||||||
|
if(_obj == noone) {
|
||||||
|
_obj = new class();
|
||||||
|
} else if(!is_instanceof(_obj, class)) {
|
||||||
|
_obj.destroy();
|
||||||
|
_obj = new class();
|
||||||
|
}
|
||||||
|
|
||||||
|
cached_object[index] = _obj;
|
||||||
|
return _obj;
|
||||||
|
} #endregion
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// 2024-05-01 08:40:49
|
// 2024-05-01 08:42:42
|
||||||
function colorSelector(onApply = noone) constructor {
|
function colorSelector(onApply = noone) constructor {
|
||||||
self.onApply = onApply;
|
self.onApply = onApply;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// 2024-05-01 08:40:09
|
// 2024-05-01 08:42:38
|
||||||
function colorSelector(onApply = noone) constructor {
|
function colorSelector(onApply = noone) constructor {
|
||||||
self.onApply = onApply;
|
self.onApply = onApply;
|
||||||
|
|
||||||
|
|
23
#backups/scripts/d3d_bbox/d3d_bbox.gml.backup0
Normal file
23
#backups/scripts/d3d_bbox/d3d_bbox.gml.backup0
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// 2024-05-01 15:56:10
|
||||||
|
function __bbox3D(first, second) constructor {
|
||||||
|
self.first = first;
|
||||||
|
self.second = second;
|
||||||
|
|
||||||
|
static getScale = function() {
|
||||||
|
INLINE
|
||||||
|
return sqrt(
|
||||||
|
sqr(first.x - second.x) +
|
||||||
|
sqr(first.y - second.y) +
|
||||||
|
sqr(first.z - second.z)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static getMaximumScale = function() {
|
||||||
|
INLINE
|
||||||
|
return max(
|
||||||
|
abs(first.x - second.x),
|
||||||
|
abs(first.y - second.y),
|
||||||
|
abs(first.z - second.z),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
23
#backups/scripts/d3d_bbox/d3d_bbox.gml.backup1
Normal file
23
#backups/scripts/d3d_bbox/d3d_bbox.gml.backup1
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// 2024-05-01 15:56:08
|
||||||
|
function __bbox3D(first, second) constructor {
|
||||||
|
self.first = first;
|
||||||
|
self.second = second;
|
||||||
|
|
||||||
|
static getScale = function() {
|
||||||
|
INLINE
|
||||||
|
return sqrt(
|
||||||
|
sqr(first.x - second.x) +
|
||||||
|
sqr(first.y - second.y) +
|
||||||
|
sqr(first.z - second.z)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static getMaximumScale = function() {
|
||||||
|
INLINE
|
||||||
|
return max(
|
||||||
|
abs(first.x - second.x),
|
||||||
|
abs(first.y - second.y),
|
||||||
|
abs(first.z - second.z),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
253
#backups/scripts/d3d_object/d3d_object.gml.backup0
Normal file
253
#backups/scripts/d3d_object/d3d_object.gml.backup0
Normal file
|
@ -0,0 +1,253 @@
|
||||||
|
// 2024-05-01 15:54:59
|
||||||
|
#region vertex format
|
||||||
|
vertex_format_begin();
|
||||||
|
vertex_format_add_position_3d();
|
||||||
|
vertex_format_add_color();
|
||||||
|
global.VF_POS_COL = vertex_format_end();
|
||||||
|
|
||||||
|
vertex_format_begin();
|
||||||
|
vertex_format_add_position_3d();
|
||||||
|
vertex_format_add_normal();
|
||||||
|
vertex_format_add_texcoord();
|
||||||
|
vertex_format_add_color();
|
||||||
|
global.VF_POS_NORM_TEX_COL = vertex_format_end();
|
||||||
|
global.VF_POS_NORM_TEX_COL_size = 36;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
function __3dObject() constructor {
|
||||||
|
vertex = [];
|
||||||
|
normal_vertex = [];
|
||||||
|
object_counts = 1;
|
||||||
|
VB = [];
|
||||||
|
|
||||||
|
NVB = noone;
|
||||||
|
normal_draw_size = 0.2;
|
||||||
|
|
||||||
|
VF = global.VF_POS_COL;
|
||||||
|
render_type = pr_trianglelist;
|
||||||
|
|
||||||
|
custom_shader = noone;
|
||||||
|
|
||||||
|
transform = new __transform();
|
||||||
|
size = new __vec3(1);
|
||||||
|
|
||||||
|
materials = [];
|
||||||
|
material_index = [];
|
||||||
|
texture_flip = false;
|
||||||
|
|
||||||
|
static checkParameter = function(params = {}, forceUpdate = false) { #region
|
||||||
|
var _keys = struct_get_names(params);
|
||||||
|
var check = false;
|
||||||
|
for( var i = 0, n = array_length(_keys); i < n; i++ ) {
|
||||||
|
var key = _keys[i];
|
||||||
|
if(self[$ key] != params[$ key])
|
||||||
|
check = true;
|
||||||
|
self[$ key] = params[$ key];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(forceUpdate || check) onParameterUpdate();
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static onParameterUpdate = function() {}
|
||||||
|
|
||||||
|
static generateNormal = function(_s = normal_draw_size) { #region
|
||||||
|
if(render_type != pr_trianglelist) return;
|
||||||
|
|
||||||
|
NVB = array_create(object_counts);
|
||||||
|
|
||||||
|
for( var i = 0; i < object_counts; i++ ) {
|
||||||
|
NVB[i] = vertex_create_buffer();
|
||||||
|
|
||||||
|
vertex_begin(NVB[i], global.VF_POS_COL);
|
||||||
|
for( var j = 0, n = array_length(vertex[i]); j < n; j++ ) {
|
||||||
|
var _v = vertex[i][j];
|
||||||
|
|
||||||
|
vertex_position_3d(NVB[i], _v.x, _v.y, _v.z);
|
||||||
|
vertex_color(NVB[i], c_red, 1);
|
||||||
|
|
||||||
|
vertex_position_3d(NVB[i], _v.x + _v.nx * _s, _v.y + _v.ny * _s, _v.z + _v.nz * _s);
|
||||||
|
vertex_color(NVB[i], c_red, 1);
|
||||||
|
}
|
||||||
|
vertex_end(NVB[i]);
|
||||||
|
}
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static buildVertex = function(_vertex) { #region
|
||||||
|
var _buffer = vertex_create_buffer();
|
||||||
|
vertex_begin(_buffer, VF);
|
||||||
|
for( var i = 0, n = array_length(_vertex); i < n; i++ ) {
|
||||||
|
var v = _vertex[i];
|
||||||
|
|
||||||
|
switch(VF) {
|
||||||
|
case global.VF_POS_COL : vertex_add_vc(_buffer, v); break;
|
||||||
|
case global.VF_POS_NORM_TEX_COL : vertex_add_vntc(_buffer, v); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vertex_end(_buffer);
|
||||||
|
//vertex_freeze(_buffer);
|
||||||
|
|
||||||
|
return _buffer;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static build = function(_buffer = VB, _vertex = vertex, counts = object_counts) { #region
|
||||||
|
if(is_array(_buffer)) {
|
||||||
|
for( var i = 0, n = array_length(_buffer); i < n; i++ )
|
||||||
|
if(_buffer[i] != noone) vertex_delete_buffer(_buffer[i])
|
||||||
|
} else if(_buffer != noone) vertex_delete_buffer(_buffer);
|
||||||
|
|
||||||
|
if(array_empty(_vertex)) return noone;
|
||||||
|
|
||||||
|
var _res = array_create(counts);
|
||||||
|
for( var i = 0; i < counts; i++ )
|
||||||
|
_res[i] = buildVertex(_vertex[i]);
|
||||||
|
|
||||||
|
return _res;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static preSubmitVertex = function(scene = {}) {}
|
||||||
|
static postSubmitVertex = function(scene = {}) {}
|
||||||
|
|
||||||
|
static getCenter = function() { return new __vec3(transform.position.x, transform.position.y, transform.position.z); }
|
||||||
|
static getBBOX = function() { return new __bbox3D(size.multiplyVec(transform.scale).multiply(-0.5), size.multiplyVec(transform.scale).multiply(0.5)); }
|
||||||
|
|
||||||
|
static submit = function(scene = {}, shader = noone) { submitVertex(scene, shader); }
|
||||||
|
static submitUI = function(scene = {}, shader = noone) { submitVertex(scene, shader); }
|
||||||
|
static submitSel = function(scene = {}, shader = noone) { #region
|
||||||
|
var _s = variable_clone(scene);
|
||||||
|
_s.show_normal = false;
|
||||||
|
submitVertex(_s, sh_d3d_silhouette);
|
||||||
|
} #endregion
|
||||||
|
static submitShader = function(scene = {}, shader = noone) {}
|
||||||
|
static submitShadow = function(scene = {}, object = noone) {}
|
||||||
|
|
||||||
|
static submitVertex = function(scene = {}, shader = noone) { #region
|
||||||
|
var _shader = sh_d3d_default;
|
||||||
|
|
||||||
|
switch(VF) {
|
||||||
|
case global.VF_POS_NORM_TEX_COL: _shader = sh_d3d_default; break;
|
||||||
|
case global.VF_POS_COL: _shader = sh_d3d_wireframe; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(custom_shader != noone) _shader = custom_shader;
|
||||||
|
if(shader != noone) _shader = shader;
|
||||||
|
|
||||||
|
shader_set(_shader);
|
||||||
|
|
||||||
|
preSubmitVertex(scene);
|
||||||
|
|
||||||
|
transform.submitMatrix();
|
||||||
|
|
||||||
|
matrix_set(matrix_world, matrix_stack_top());
|
||||||
|
|
||||||
|
#region ++++ Submit & Material ++++
|
||||||
|
gpu_set_tex_repeat(true);
|
||||||
|
|
||||||
|
for( var i = 0, n = array_length(VB); i < n; i++ ) {
|
||||||
|
var _ind = array_safe_get_fast(material_index, i, i);
|
||||||
|
var _mat = array_safe_get_fast(materials, _ind, noone);
|
||||||
|
var _useMat = is_instanceof(_mat, __d3dMaterial);
|
||||||
|
|
||||||
|
shader_set_i("mat_flip", texture_flip);
|
||||||
|
var _tex = _useMat? _mat.getTexture() : -1;
|
||||||
|
|
||||||
|
if(_shader == sh_d3d_default) {
|
||||||
|
if(_useMat) {
|
||||||
|
_mat.submitShader();
|
||||||
|
} else {
|
||||||
|
shader_set_f("mat_diffuse", 1);
|
||||||
|
shader_set_f("mat_specular", 0);
|
||||||
|
shader_set_f("mat_shine", 1);
|
||||||
|
shader_set_i("mat_metalic", 0);
|
||||||
|
shader_set_f("mat_reflective", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
vertex_submit(VB[i], render_type, _tex);
|
||||||
|
} else if(_shader == sh_d3d_geometry) {
|
||||||
|
if(_useMat)
|
||||||
|
_mat.submitGeometry();
|
||||||
|
else
|
||||||
|
shader_set_i("use_normal", 0);
|
||||||
|
|
||||||
|
vertex_submit(VB[i], render_type, _tex);
|
||||||
|
} else
|
||||||
|
vertex_submit(VB[i], render_type, _tex);
|
||||||
|
|
||||||
|
// print($"Submit vertex ({scene}) [{VB[i]}: {vertex_get_buffer_size(VB[i])}]");
|
||||||
|
}
|
||||||
|
|
||||||
|
gpu_set_tex_repeat(false);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
shader_reset();
|
||||||
|
|
||||||
|
if(scene.show_normal) { #region
|
||||||
|
if(NVB == noone) generateNormal();
|
||||||
|
if(NVB != noone) {
|
||||||
|
shader_set(sh_d3d_wireframe);
|
||||||
|
shader_set_color("blend", c_white);
|
||||||
|
|
||||||
|
for( var i = 0, n = array_length(NVB); i < n; i++ )
|
||||||
|
vertex_submit(NVB[i], pr_linelist, -1);
|
||||||
|
shader_reset();
|
||||||
|
}
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
transform.clearMatrix();
|
||||||
|
matrix_set(matrix_world, matrix_build_identity());
|
||||||
|
|
||||||
|
postSubmitVertex(scene);
|
||||||
|
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static clone = function(_vertex = true, cloneBuffer = false) { #region
|
||||||
|
var _obj = new __3dObject();
|
||||||
|
|
||||||
|
if(_vertex) {
|
||||||
|
_obj.vertex = array_create(array_length(vertex));
|
||||||
|
for( var i = 0, n = array_length(vertex); i < n; i++ ) {
|
||||||
|
_obj.vertex[i] = array_create(array_length(vertex[i]));
|
||||||
|
|
||||||
|
for( var j = 0, m = array_length(vertex[i]); j < m; j++ )
|
||||||
|
_obj.vertex[i][j] = vertex[i][j].clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cloneBuffer) {
|
||||||
|
_obj.VB = array_create(array_length(VB));
|
||||||
|
|
||||||
|
for( var i = 0, n = array_length(VB); i < n; i++ ) {
|
||||||
|
var _vnum = vertex_get_number(VB[i]);
|
||||||
|
var _buff = buffer_create(1, buffer_grow, 1);
|
||||||
|
buffer_copy_from_vertex_buffer(VB[i], 0, _vnum - 1, _buff, 0);
|
||||||
|
|
||||||
|
_obj.VB[i] = vertex_create_buffer_from_buffer(_buff, VF);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_obj.VB = VB;
|
||||||
|
}
|
||||||
|
|
||||||
|
_obj.NVB = NVB;
|
||||||
|
_obj.VF = VF;
|
||||||
|
_obj.render_type = render_type;
|
||||||
|
_obj.custom_shader = custom_shader;
|
||||||
|
_obj.object_counts = object_counts;
|
||||||
|
_obj.transform = transform.clone();
|
||||||
|
_obj.size = size.clone();
|
||||||
|
_obj.materials = materials;
|
||||||
|
_obj.material_index = material_index;
|
||||||
|
_obj.texture_flip = texture_flip;
|
||||||
|
|
||||||
|
return _obj;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static destroy = function() { #region
|
||||||
|
for( var i = 0, n = array_length(VB); i < n; i++ )
|
||||||
|
vertex_delete_buffer(VB[i]);
|
||||||
|
VB = [];
|
||||||
|
onDestroy();
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static onDestroy = function() { }
|
||||||
|
|
||||||
|
static toString = function() { return $"[D3D Object]\n\t({array_length(vertex)} vertex groups\n\tPosition: {transform.position}\n\tRotation: {transform.rotation}\n\tScale: {transform.scale})" }
|
||||||
|
}
|
253
#backups/scripts/d3d_object/d3d_object.gml.backup1
Normal file
253
#backups/scripts/d3d_object/d3d_object.gml.backup1
Normal file
|
@ -0,0 +1,253 @@
|
||||||
|
// 2024-05-01 15:51:30
|
||||||
|
#region vertex format
|
||||||
|
vertex_format_begin();
|
||||||
|
vertex_format_add_position_3d();
|
||||||
|
vertex_format_add_color();
|
||||||
|
global.VF_POS_COL = vertex_format_end();
|
||||||
|
|
||||||
|
vertex_format_begin();
|
||||||
|
vertex_format_add_position_3d();
|
||||||
|
vertex_format_add_normal();
|
||||||
|
vertex_format_add_texcoord();
|
||||||
|
vertex_format_add_color();
|
||||||
|
global.VF_POS_NORM_TEX_COL = vertex_format_end();
|
||||||
|
global.VF_POS_NORM_TEX_COL_size = 36;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
function __3dObject() constructor {
|
||||||
|
vertex = [];
|
||||||
|
normal_vertex = [];
|
||||||
|
object_counts = 1;
|
||||||
|
VB = [];
|
||||||
|
|
||||||
|
NVB = noone;
|
||||||
|
normal_draw_size = 0.2;
|
||||||
|
|
||||||
|
VF = global.VF_POS_COL;
|
||||||
|
render_type = pr_trianglelist;
|
||||||
|
|
||||||
|
custom_shader = noone;
|
||||||
|
|
||||||
|
transform = new __transform();
|
||||||
|
size = new __vec3(1);
|
||||||
|
|
||||||
|
materials = [];
|
||||||
|
material_index = [];
|
||||||
|
texture_flip = false;
|
||||||
|
|
||||||
|
static checkParameter = function(params = {}, forceUpdate = false) { #region
|
||||||
|
var _keys = struct_get_names(params);
|
||||||
|
var check = false;
|
||||||
|
for( var i = 0, n = array_length(_keys); i < n; i++ ) {
|
||||||
|
var key = _keys[i];
|
||||||
|
if(self[$ key] != params[$ key])
|
||||||
|
check = true;
|
||||||
|
self[$ key] = params[$ key];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(forceUpdate || check) onParameterUpdate();
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static onParameterUpdate = function() {}
|
||||||
|
|
||||||
|
static generateNormal = function(_s = normal_draw_size) { #region
|
||||||
|
if(render_type != pr_trianglelist) return;
|
||||||
|
|
||||||
|
NVB = array_create(object_counts);
|
||||||
|
|
||||||
|
for( var i = 0; i < object_counts; i++ ) {
|
||||||
|
NVB[i] = vertex_create_buffer();
|
||||||
|
|
||||||
|
vertex_begin(NVB[i], global.VF_POS_COL);
|
||||||
|
for( var j = 0, n = array_length(vertex[i]); j < n; j++ ) {
|
||||||
|
var _v = vertex[i][j];
|
||||||
|
|
||||||
|
vertex_position_3d(NVB[i], _v.x, _v.y, _v.z);
|
||||||
|
vertex_color(NVB[i], c_red, 1);
|
||||||
|
|
||||||
|
vertex_position_3d(NVB[i], _v.x + _v.nx * _s, _v.y + _v.ny * _s, _v.z + _v.nz * _s);
|
||||||
|
vertex_color(NVB[i], c_red, 1);
|
||||||
|
}
|
||||||
|
vertex_end(NVB[i]);
|
||||||
|
}
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static buildVertex = function(_vertex) { #region
|
||||||
|
var _buffer = vertex_create_buffer();
|
||||||
|
vertex_begin(_buffer, VF);
|
||||||
|
for( var i = 0, n = array_length(_vertex); i < n; i++ ) {
|
||||||
|
var v = _vertex[i];
|
||||||
|
|
||||||
|
switch(VF) {
|
||||||
|
case global.VF_POS_COL : vertex_add_vc(_buffer, v); break;
|
||||||
|
case global.VF_POS_NORM_TEX_COL : vertex_add_vntc(_buffer, v); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vertex_end(_buffer);
|
||||||
|
//vertex_freeze(_buffer);
|
||||||
|
|
||||||
|
return _buffer;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static build = function(_buffer = VB, _vertex = vertex, counts = object_counts) { #region
|
||||||
|
if(is_array(_buffer)) {
|
||||||
|
for( var i = 0, n = array_length(_buffer); i < n; i++ )
|
||||||
|
if(_buffer[i] != noone) vertex_delete_buffer(_buffer[i])
|
||||||
|
} else if(_buffer != noone) vertex_delete_buffer(_buffer);
|
||||||
|
|
||||||
|
if(array_empty(_vertex)) return noone;
|
||||||
|
|
||||||
|
var _res = array_create(counts);
|
||||||
|
for( var i = 0; i < counts; i++ )
|
||||||
|
_res[i] = buildVertex(_vertex[i]);
|
||||||
|
|
||||||
|
return _res;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static preSubmitVertex = function(scene = {}) {}
|
||||||
|
static postSubmitVertex = function(scene = {}) {}
|
||||||
|
|
||||||
|
static getCenter = function() { return new __vec3(transform.position.x, transform.position.y, transform.position.z); }
|
||||||
|
static getBBOX = function() { return new __bbox3D(size.multiplyVec(transform.scale).multiply(-0.5), size.multiplyVec(transform.scale).multiply(0.5)); }
|
||||||
|
|
||||||
|
static submit = function(scene = {}, shader = noone) { submitVertex(scene, shader); }
|
||||||
|
static submitUI = function(scene = {}, shader = noone) { submitVertex(scene, shader); }
|
||||||
|
static submitSel = function(scene = {}, shader = noone) { #region
|
||||||
|
var _s = variable_clone(scene);
|
||||||
|
_s.show_normal = false;
|
||||||
|
submitVertex(_s, sh_d3d_silhouette);
|
||||||
|
} #endregion
|
||||||
|
static submitShader = function(scene = {}, shader = noone) {}
|
||||||
|
static submitShadow = function(scene = {}, object = noone) {}
|
||||||
|
|
||||||
|
static submitVertex = function(scene = {}, shader = noone) { #region
|
||||||
|
var _shader = sh_d3d_default;
|
||||||
|
|
||||||
|
switch(VF) {
|
||||||
|
case global.VF_POS_NORM_TEX_COL: _shader = sh_d3d_default; break;
|
||||||
|
case global.VF_POS_COL: _shader = sh_d3d_wireframe; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(custom_shader != noone) _shader = custom_shader;
|
||||||
|
if(shader != noone) _shader = shader;
|
||||||
|
|
||||||
|
shader_set(_shader);
|
||||||
|
|
||||||
|
preSubmitVertex(scene);
|
||||||
|
|
||||||
|
transform.submitMatrix();
|
||||||
|
|
||||||
|
matrix_set(matrix_world, matrix_stack_top());
|
||||||
|
|
||||||
|
#region ++++ Submit & Material ++++
|
||||||
|
gpu_set_tex_repeat(true);
|
||||||
|
|
||||||
|
for( var i = 0, n = array_length(VB); i < n; i++ ) {
|
||||||
|
var _ind = array_safe_get_fast(material_index, i, i);
|
||||||
|
var _mat = array_safe_get_fast(materials, _ind, noone);
|
||||||
|
var _useMat = is_instanceof(_mat, __d3dMaterial);
|
||||||
|
|
||||||
|
shader_set_i("mat_flip", texture_flip);
|
||||||
|
var _tex = _useMat? _mat.getTexture() : -1;
|
||||||
|
|
||||||
|
if(_shader == sh_d3d_default) {
|
||||||
|
if(_useMat) {
|
||||||
|
_mat.submitShader();
|
||||||
|
} else {
|
||||||
|
shader_set_f("mat_diffuse", 1);
|
||||||
|
shader_set_f("mat_specular", 0);
|
||||||
|
shader_set_f("mat_shine", 1);
|
||||||
|
shader_set_i("mat_metalic", 0);
|
||||||
|
shader_set_f("mat_reflective", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
vertex_submit(VB[i], render_type, _tex);
|
||||||
|
} else if(_shader == sh_d3d_geometry) {
|
||||||
|
if(_useMat)
|
||||||
|
_mat.submitGeometry();
|
||||||
|
else
|
||||||
|
shader_set_i("use_normal", 0);
|
||||||
|
|
||||||
|
vertex_submit(VB[i], render_type, _tex);
|
||||||
|
} else
|
||||||
|
vertex_submit(VB[i], render_type, _tex);
|
||||||
|
|
||||||
|
// print($"Submit vertex ({scene}) [{VB[i]}: {vertex_get_buffer_size(VB[i])}]");
|
||||||
|
}
|
||||||
|
|
||||||
|
gpu_set_tex_repeat(false);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
shader_reset();
|
||||||
|
|
||||||
|
if(scene.show_normal) { #region
|
||||||
|
if(NVB == noone) generateNormal();
|
||||||
|
if(NVB != noone) {
|
||||||
|
shader_set(sh_d3d_wireframe);
|
||||||
|
shader_set_color("blend", c_white);
|
||||||
|
|
||||||
|
for( var i = 0, n = array_length(NVB); i < n; i++ )
|
||||||
|
vertex_submit(NVB[i], pr_linelist, -1);
|
||||||
|
shader_reset();
|
||||||
|
}
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
transform.clearMatrix();
|
||||||
|
matrix_set(matrix_world, matrix_build_identity());
|
||||||
|
|
||||||
|
postSubmitVertex(scene);
|
||||||
|
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static clone = function(_vertex = true, cloneBuffer = false) { #region
|
||||||
|
var _obj = new __3dObject();
|
||||||
|
|
||||||
|
if(_vertex) {
|
||||||
|
_obj.vertex = array_create(array_length(vertex));
|
||||||
|
for( var i = 0, n = array_length(vertex); i < n; i++ ) {
|
||||||
|
_obj.vertex[i] = array_create(array_length(vertex[i]));
|
||||||
|
|
||||||
|
for( var j = 0, m = array_length(vertex[i]); j < m; j++ )
|
||||||
|
_obj.vertex[i][j] = vertex[i][j].clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cloneBuffer) {
|
||||||
|
_obj.VB = array_create(array_length(VB));
|
||||||
|
|
||||||
|
for( var i = 0, n = array_length(VB); i < n; i++ ) {
|
||||||
|
var _vnum = vertex_get_number(VB[i]);
|
||||||
|
var _buff = buffer_create(1, buffer_grow, 1);
|
||||||
|
buffer_copy_from_vertex_buffer(VB[i], 0, _vnum - 1, _buff, 0);
|
||||||
|
|
||||||
|
_obj.VB[i] = vertex_create_buffer_from_buffer(_buff, VF);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_obj.VB = VB;
|
||||||
|
}
|
||||||
|
|
||||||
|
_obj.NVB = NVB;
|
||||||
|
_obj.VF = VF;
|
||||||
|
_obj.render_type = render_type;
|
||||||
|
_obj.custom_shader = custom_shader;
|
||||||
|
_obj.object_counts = object_counts;
|
||||||
|
_obj.transform = transform.clone();
|
||||||
|
_obj.size = size.clone();
|
||||||
|
_obj.materials = materials;
|
||||||
|
_obj.material_index = material_index;
|
||||||
|
_obj.texture_flip = texture_flip;
|
||||||
|
|
||||||
|
return _obj;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static destroy = function() { #region
|
||||||
|
for( var i = 0, n = array_length(VB); i < n; i++ )
|
||||||
|
vertex_delete_buffer(VB[i]);
|
||||||
|
VB = [];
|
||||||
|
onDestroy();
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static onDestroy = function() { }
|
||||||
|
|
||||||
|
static toString = function() { return $"[D3D Object]\n\t({array_length(vertex)} vertex groups\n\tPosition: {transform.position}\n\tRotation: {transform.rotation}\n\tScale: {transform.scale})" }
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// 2024-05-01 08:11:39
|
// 2024-05-01 08:42:51
|
||||||
#region save
|
#region save
|
||||||
globalvar LOADING, CLONING, CLONING_GROUP;
|
globalvar LOADING, CLONING, CLONING_GROUP;
|
||||||
globalvar CONNECTION_CONFLICT, LOADING_VERSION;
|
globalvar CONNECTION_CONFLICT, LOADING_VERSION;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// 2024-05-01 08:11:28
|
// 2024-05-01 08:42:50
|
||||||
#region save
|
#region save
|
||||||
globalvar LOADING, CLONING, CLONING_GROUP;
|
globalvar LOADING, CLONING, CLONING_GROUP;
|
||||||
globalvar CONNECTION_CONFLICT, LOADING_VERSION;
|
globalvar CONNECTION_CONFLICT, LOADING_VERSION;
|
||||||
|
|
243
#backups/scripts/node_3d_mesh_obj/node_3d_mesh_obj.gml.backup0
Normal file
243
#backups/scripts/node_3d_mesh_obj/node_3d_mesh_obj.gml.backup0
Normal file
|
@ -0,0 +1,243 @@
|
||||||
|
// 2024-05-01 15:53:22
|
||||||
|
function Node_create_3D_Obj(_x, _y, _group = noone) { #region
|
||||||
|
var path = "";
|
||||||
|
if(!LOADING && !APPENDING && !CLONING) {
|
||||||
|
path = get_open_filename("3d object|*.obj", "");
|
||||||
|
key_release();
|
||||||
|
if(path == "") return noone;
|
||||||
|
}
|
||||||
|
|
||||||
|
var node = new Node_3D_Mesh_Obj(_x, _y, _group);
|
||||||
|
node.setPath(path);
|
||||||
|
return node;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
function Node_create_3D_Obj_path(_x, _y, path) { #region
|
||||||
|
if(!file_exists_empty(path)) return noone;
|
||||||
|
|
||||||
|
var node = new Node_3D_Mesh_Obj(_x, _y, PANEL_GRAPH.getCurrentContext());
|
||||||
|
node.setPath(path);
|
||||||
|
return node;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
function Node_3D_Mesh_Obj(_x, _y, _group = noone) : Node_3D_Mesh(_x, _y, _group) constructor {
|
||||||
|
name = "3D Obj";
|
||||||
|
|
||||||
|
object = noone;
|
||||||
|
object_class = __3dObject;
|
||||||
|
|
||||||
|
inputs[| in_mesh + 0] = nodeValue("File Path", self, JUNCTION_CONNECT.input, VALUE_TYPE.path, "" )
|
||||||
|
.setDisplay(VALUE_DISPLAY.path_load, { filter: "3d object|*.obj" })
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
inputs[| in_mesh + 1] = nodeValue("Flip UV", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true, "Flip UV axis, can be use to fix some texture mapping error.")
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
inputs[| in_mesh + 2] = nodeValue("Import Scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1)
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
input_display_list = [
|
||||||
|
__d3d_input_list_mesh,
|
||||||
|
__d3d_input_list_transform,
|
||||||
|
["Object", false], in_mesh + 0, in_mesh + 2,
|
||||||
|
["Material", false], in_mesh + 1,
|
||||||
|
]
|
||||||
|
|
||||||
|
setIsDynamicInput(1);
|
||||||
|
|
||||||
|
obj_reading = false;
|
||||||
|
obj_raw = noone;
|
||||||
|
obj_read_progress = 0;
|
||||||
|
obj_read_prog_sub = 0;
|
||||||
|
obj_read_prog_tot = 3;
|
||||||
|
obj_read_time = 0;
|
||||||
|
|
||||||
|
current_path = "";
|
||||||
|
materials = [];
|
||||||
|
materialNames = [];
|
||||||
|
materialIndex = [];
|
||||||
|
use_normal = false;
|
||||||
|
|
||||||
|
insp1UpdateTooltip = __txt("Refresh");
|
||||||
|
insp1UpdateIcon = [ THEME.refresh_icon, 1, COLORS._main_value_positive ];
|
||||||
|
|
||||||
|
static onInspector1Update = function() {
|
||||||
|
current_path = "";
|
||||||
|
outputs[| 0].setValue(noone);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPath(path) { inputs[| in_mesh + 0].setValue(path); }
|
||||||
|
|
||||||
|
static createNewInput = function(index = -1) { #region
|
||||||
|
if(index == -1) index = ds_list_size(inputs);
|
||||||
|
|
||||||
|
inputs[| index] = nodeValue("Material", self, JUNCTION_CONNECT.input, VALUE_TYPE.d3Material, new __d3dMaterial())
|
||||||
|
.setVisible(true, true);
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static createMaterial = function(m_index) { #region
|
||||||
|
var index = input_fix_len + m_index;
|
||||||
|
|
||||||
|
input_display_list[input_display_len + m_index] = index;
|
||||||
|
if(index < ds_list_size(inputs)) return;
|
||||||
|
|
||||||
|
createNewInput(index);
|
||||||
|
|
||||||
|
if(m_index >= array_length(materials)) return;
|
||||||
|
|
||||||
|
var matY = y - (array_length(materials) - 1) / 2 * (128 + 32);
|
||||||
|
var mat = materials[m_index];
|
||||||
|
inputs[| index].name = materialNames[m_index] + " Material";
|
||||||
|
|
||||||
|
if(file_exists_empty(mat.diff_path)) {
|
||||||
|
var sol = Node_create_Image_path(x - (w + 128), matY + m_index * (128 + 32), mat.diff_path);
|
||||||
|
sol.name = mat.name + " texture";
|
||||||
|
|
||||||
|
inputs[| index].setFrom(sol.outputs[| 0]);
|
||||||
|
} else {
|
||||||
|
var sol = nodeBuild("Node_Solid", x - (w + 128), matY + m_index * (128 + 32));
|
||||||
|
sol.name = mat.name + " texture";
|
||||||
|
sol.inputs[| 1].setValue(mat.diff);
|
||||||
|
|
||||||
|
inputs[| index].setFrom(sol.outputs[| 0]);
|
||||||
|
}
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static updateObj = function(_path) { #region
|
||||||
|
if(!file_exists_empty(_path)) return;
|
||||||
|
current_path = _path;
|
||||||
|
|
||||||
|
var _scale = inputs[| in_mesh + 2].getValue();
|
||||||
|
|
||||||
|
readObj_init(_scale);
|
||||||
|
|
||||||
|
obj_read_time = get_timer();
|
||||||
|
obj_read_file = file_text_open_read(current_path);
|
||||||
|
use_display_list = false;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static updateObjProcess = function() { #region
|
||||||
|
switch(obj_read_progress) {
|
||||||
|
case 0 : readObj_file(); break;
|
||||||
|
case 1 : readObj_cent(); break;
|
||||||
|
case 2 : readObj_buff(); break;
|
||||||
|
}
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static updateObjComplete = function() { #region
|
||||||
|
use_display_list = true;
|
||||||
|
if(obj_raw == noone) return;
|
||||||
|
|
||||||
|
// var txt = $"========== OBJ import ==========\n";
|
||||||
|
// txt += $"Vertex counts: {obj_raw.vertex_count}\n";
|
||||||
|
// txt += $"Object counts: {obj_raw.object_counts}\n";
|
||||||
|
// txt += $"Material counts: {array_length(obj_raw.materials)}\n";
|
||||||
|
// txt += $"Model BBOX: {obj_raw.model_size}\n";
|
||||||
|
// txt += $"Load completed in {(get_timer() - obj_read_time) / 1000} ms\n";
|
||||||
|
// print(txt);
|
||||||
|
|
||||||
|
var span = max(abs(obj_raw.model_size.x), abs(obj_raw.model_size.y), abs(obj_raw.model_size.z));
|
||||||
|
if(span > 10) noti_warning($"The model is tool large to display properly ({span}u). Scale the model down to preview.");
|
||||||
|
|
||||||
|
if(object != noone) object.destroy();
|
||||||
|
|
||||||
|
object = new __3dObject();
|
||||||
|
object.VB = obj_raw.vertex_groups;
|
||||||
|
object.vertex = obj_raw.vertex;
|
||||||
|
object.size = obj_raw.model_size;
|
||||||
|
object.object_counts = obj_raw.object_counts;
|
||||||
|
use_normal = obj_raw.use_normal;
|
||||||
|
|
||||||
|
materialNames = [ "Material" ];
|
||||||
|
materialIndex = [ 0 ];
|
||||||
|
materials = [ new MTLmaterial("Material") ];
|
||||||
|
|
||||||
|
if(array_length(materialNames)) {
|
||||||
|
var _dir = filename_dir(current_path);
|
||||||
|
var _pathMtl = string_copy(current_path, 1, string_length(current_path) - 4) + ".mtl";
|
||||||
|
if(obj_raw.mtl_path != "") _pathMtl = _dir + "/" + obj_raw.mtl_path;
|
||||||
|
materials = readMtl(_pathMtl);
|
||||||
|
|
||||||
|
if(array_length(materials) == array_length(obj_raw.materials)) {
|
||||||
|
materialNames = array_create(array_length(materials));
|
||||||
|
for( var i = 0, n = array_length(materials); i < n; i++ )
|
||||||
|
materialNames[i] = materials[i].name;
|
||||||
|
|
||||||
|
for( var i = 0, n = array_length(materials); i < n; i++ ) {
|
||||||
|
var _mat = obj_raw.materials[i];
|
||||||
|
var _ord = array_find(materialNames, _mat);
|
||||||
|
materialIndex[i] = _ord;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
noti_warning("Load mtl error: Material amount defined in .mtl file not match the .obj file.")
|
||||||
|
}
|
||||||
|
|
||||||
|
array_resize(input_display_list, input_display_len);
|
||||||
|
|
||||||
|
var _overflow = input_fix_len + array_length(materialNames);
|
||||||
|
while(ds_list_size(inputs) > _overflow)
|
||||||
|
ds_list_delete(inputs, _overflow);
|
||||||
|
|
||||||
|
for(var i = 0; i < array_length(materialNames); i++)
|
||||||
|
createMaterial(i);
|
||||||
|
|
||||||
|
outputs[| 0].setValue(object);
|
||||||
|
|
||||||
|
triggerRender();
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static step = function() { #region
|
||||||
|
if(obj_reading) {
|
||||||
|
updateObjProcess();
|
||||||
|
|
||||||
|
if(obj_read_progress == obj_read_prog_tot) {
|
||||||
|
updateObjComplete();
|
||||||
|
obj_reading = false;
|
||||||
|
|
||||||
|
triggerRender();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _path = getInputData(in_mesh + 0);
|
||||||
|
if(_path != current_path) updateObj(_path);
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static processData = function(_output, _data, _output_index, _array_index = 0) { #region
|
||||||
|
if(obj_reading) return noone;
|
||||||
|
|
||||||
|
var _flip = _data[in_mesh + 1];
|
||||||
|
|
||||||
|
if(object == noone) return noone;
|
||||||
|
var materials = [];
|
||||||
|
for( var i = input_fix_len, n = array_length(_data); i < n; i++ )
|
||||||
|
materials[i - input_fix_len] = _data[i];
|
||||||
|
|
||||||
|
var _object = getObject(_array_index);
|
||||||
|
_object.VF = global.VF_POS_NORM_TEX_COL;
|
||||||
|
_object.VB = object.VB;
|
||||||
|
_object.NVB = object.NVB;
|
||||||
|
_object.vertex = object.vertex;
|
||||||
|
_object.size = object.size;
|
||||||
|
_object.object_counts = object.object_counts;
|
||||||
|
_object.materials = materials;
|
||||||
|
_object.material_index = materialIndex;
|
||||||
|
_object.texture_flip = _flip;
|
||||||
|
|
||||||
|
setTransform(_object, _data);
|
||||||
|
return _object;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static getPreviewValues = function() { return array_safe_get_fast(all_inputs, in_mesh + 2, noone); }
|
||||||
|
|
||||||
|
static onDrawNodeOver = function(xx, yy, _mx, _my, _s, _hover, _focus) { #region
|
||||||
|
if(!obj_reading) return;
|
||||||
|
|
||||||
|
var cx = xx + w * _s / 2;
|
||||||
|
var cy = yy + h * _s / 2;
|
||||||
|
var rr = min(w - 32, h - 32) * _s / 2;
|
||||||
|
|
||||||
|
draw_set_color(COLORS._main_icon);
|
||||||
|
draw_arc(cx, cy, rr, current_time / 5, current_time / 5 + 90, 4 * _s, 90);
|
||||||
|
} #endregion
|
||||||
|
}
|
243
#backups/scripts/node_3d_mesh_obj/node_3d_mesh_obj.gml.backup1
Normal file
243
#backups/scripts/node_3d_mesh_obj/node_3d_mesh_obj.gml.backup1
Normal file
|
@ -0,0 +1,243 @@
|
||||||
|
// 2024-05-01 15:53:20
|
||||||
|
function Node_create_3D_Obj(_x, _y, _group = noone) { #region
|
||||||
|
var path = "";
|
||||||
|
if(!LOADING && !APPENDING && !CLONING) {
|
||||||
|
path = get_open_filename("3d object|*.obj", "");
|
||||||
|
key_release();
|
||||||
|
if(path == "") return noone;
|
||||||
|
}
|
||||||
|
|
||||||
|
var node = new Node_3D_Mesh_Obj(_x, _y, _group);
|
||||||
|
node.setPath(path);
|
||||||
|
return node;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
function Node_create_3D_Obj_path(_x, _y, path) { #region
|
||||||
|
if(!file_exists_empty(path)) return noone;
|
||||||
|
|
||||||
|
var node = new Node_3D_Mesh_Obj(_x, _y, PANEL_GRAPH.getCurrentContext());
|
||||||
|
node.setPath(path);
|
||||||
|
return node;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
function Node_3D_Mesh_Obj(_x, _y, _group = noone) : Node_3D_Mesh(_x, _y, _group) constructor {
|
||||||
|
name = "3D Obj";
|
||||||
|
|
||||||
|
object = noone;
|
||||||
|
object_class = __3dObject;
|
||||||
|
|
||||||
|
inputs[| in_mesh + 0] = nodeValue("File Path", self, JUNCTION_CONNECT.input, VALUE_TYPE.path, "" )
|
||||||
|
.setDisplay(VALUE_DISPLAY.path_load, { filter: "3d object|*.obj" })
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
inputs[| in_mesh + 1] = nodeValue("Flip UV", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true, "Flip UV axis, can be use to fix some texture mapping error.")
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
inputs[| in_mesh + 2] = nodeValue("Import Scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1)
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
input_display_list = [
|
||||||
|
__d3d_input_list_mesh,
|
||||||
|
__d3d_input_list_transform,
|
||||||
|
["Object", false], in_mesh + 0, in_mesh + 2,
|
||||||
|
["Material", false], in_mesh + 1,
|
||||||
|
]
|
||||||
|
|
||||||
|
setIsDynamicInput(1);
|
||||||
|
|
||||||
|
obj_reading = false;
|
||||||
|
obj_raw = noone;
|
||||||
|
obj_read_progress = 0;
|
||||||
|
obj_read_prog_sub = 0;
|
||||||
|
obj_read_prog_tot = 3;
|
||||||
|
obj_read_time = 0;
|
||||||
|
|
||||||
|
current_path = "";
|
||||||
|
materials = [];
|
||||||
|
materialNames = [];
|
||||||
|
materialIndex = [];
|
||||||
|
use_normal = false;
|
||||||
|
|
||||||
|
insp1UpdateTooltip = __txt("Refresh");
|
||||||
|
insp1UpdateIcon = [ THEME.refresh_icon, 1, COLORS._main_value_positive ];
|
||||||
|
|
||||||
|
static onInspector1Update = function() {
|
||||||
|
current_path = "";
|
||||||
|
outputs[| 0].setValue(noone);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPath(path) { inputs[| in_mesh + 0].setValue(path); }
|
||||||
|
|
||||||
|
static createNewInput = function(index = -1) { #region
|
||||||
|
if(index == -1) index = ds_list_size(inputs);
|
||||||
|
|
||||||
|
inputs[| index] = nodeValue("Material", self, JUNCTION_CONNECT.input, VALUE_TYPE.d3Material, new __d3dMaterial())
|
||||||
|
.setVisible(true, true);
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static createMaterial = function(m_index) { #region
|
||||||
|
var index = input_fix_len + m_index;
|
||||||
|
|
||||||
|
input_display_list[input_display_len + m_index] = index;
|
||||||
|
if(index < ds_list_size(inputs)) return;
|
||||||
|
|
||||||
|
createNewInput(index);
|
||||||
|
|
||||||
|
if(m_index >= array_length(materials)) return;
|
||||||
|
|
||||||
|
var matY = y - (array_length(materials) - 1) / 2 * (128 + 32);
|
||||||
|
var mat = materials[m_index];
|
||||||
|
inputs[| index].name = materialNames[m_index] + " Material";
|
||||||
|
|
||||||
|
if(file_exists_empty(mat.diff_path)) {
|
||||||
|
var sol = Node_create_Image_path(x - (w + 128), matY + m_index * (128 + 32), mat.diff_path);
|
||||||
|
sol.name = mat.name + " texture";
|
||||||
|
|
||||||
|
inputs[| index].setFrom(sol.outputs[| 0]);
|
||||||
|
} else {
|
||||||
|
var sol = nodeBuild("Node_Solid", x - (w + 128), matY + m_index * (128 + 32));
|
||||||
|
sol.name = mat.name + " texture";
|
||||||
|
sol.inputs[| 1].setValue(mat.diff);
|
||||||
|
|
||||||
|
inputs[| index].setFrom(sol.outputs[| 0]);
|
||||||
|
}
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static updateObj = function(_path) { #region
|
||||||
|
if(!file_exists_empty(_path)) return;
|
||||||
|
current_path = _path;
|
||||||
|
|
||||||
|
var _scale = inputs[| in_mesh + 2].getValue();
|
||||||
|
|
||||||
|
readObj_init(_scale);
|
||||||
|
|
||||||
|
obj_read_time = get_timer();
|
||||||
|
obj_read_file = file_text_open_read(current_path);
|
||||||
|
use_display_list = false;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static updateObjProcess = function() { #region
|
||||||
|
switch(obj_read_progress) {
|
||||||
|
case 0 : readObj_file(); break;
|
||||||
|
case 1 : readObj_cent(); break;
|
||||||
|
case 2 : readObj_buff(); break;
|
||||||
|
}
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static updateObjComplete = function() { #region
|
||||||
|
use_display_list = true;
|
||||||
|
if(obj_raw == noone) return;
|
||||||
|
|
||||||
|
// var txt = $"========== OBJ import ==========\n";
|
||||||
|
// txt += $"Vertex counts: {obj_raw.vertex_count}\n";
|
||||||
|
// txt += $"Object counts: {obj_raw.object_counts}\n";
|
||||||
|
// txt += $"Material counts: {array_length(obj_raw.materials)}\n";
|
||||||
|
// txt += $"Model BBOX: {obj_raw.model_size}\n";
|
||||||
|
// txt += $"Load completed in {(get_timer() - obj_read_time) / 1000} ms\n";
|
||||||
|
// print(txt);
|
||||||
|
|
||||||
|
var span = max(abs(obj_raw.model_size.x), abs(obj_raw.model_size.y), abs(obj_raw.model_size.z));
|
||||||
|
if(span > 10) noti_warning($"The model is tool large to display properly ({span}u). Scale the model down to preview.");
|
||||||
|
|
||||||
|
if(object != noone) object.destroy();
|
||||||
|
|
||||||
|
object = new __3dObject();
|
||||||
|
object.VB = obj_raw.vertex_groups;
|
||||||
|
object.vertex = obj_raw.vertex;
|
||||||
|
object.size = obj_raw.model_size;
|
||||||
|
object.object_counts = obj_raw.object_counts;
|
||||||
|
use_normal = obj_raw.use_normal;
|
||||||
|
|
||||||
|
materialNames = [ "Material" ];
|
||||||
|
materialIndex = [ 0 ];
|
||||||
|
materials = [ new MTLmaterial("Material") ];
|
||||||
|
|
||||||
|
if(array_length(materialNames)) {
|
||||||
|
var _dir = filename_dir(current_path);
|
||||||
|
var _pathMtl = string_copy(current_path, 1, string_length(current_path) - 4) + ".mtl";
|
||||||
|
if(obj_raw.mtl_path != "") _pathMtl = _dir + "/" + obj_raw.mtl_path;
|
||||||
|
materials = readMtl(_pathMtl);
|
||||||
|
|
||||||
|
if(array_length(materials) == array_length(obj_raw.materials)) {
|
||||||
|
materialNames = array_create(array_length(materials));
|
||||||
|
for( var i = 0, n = array_length(materials); i < n; i++ )
|
||||||
|
materialNames[i] = materials[i].name;
|
||||||
|
|
||||||
|
for( var i = 0, n = array_length(materials); i < n; i++ ) {
|
||||||
|
var _mat = obj_raw.materials[i];
|
||||||
|
var _ord = array_find(materialNames, _mat);
|
||||||
|
materialIndex[i] = _ord;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
noti_warning("Load mtl error: Material amount defined in .mtl file not match the .obj file.")
|
||||||
|
}
|
||||||
|
|
||||||
|
array_resize(input_display_list, input_display_len);
|
||||||
|
|
||||||
|
var _overflow = input_fix_len + array_length(materialNames);
|
||||||
|
while(ds_list_size(inputs) > _overflow)
|
||||||
|
ds_list_delete(inputs, _overflow);
|
||||||
|
|
||||||
|
for(var i = 0; i < array_length(materialNames); i++)
|
||||||
|
createMaterial(i);
|
||||||
|
|
||||||
|
outputs[| 0].setValue(object);
|
||||||
|
|
||||||
|
triggerRender();
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static step = function() { #region
|
||||||
|
if(obj_reading) {
|
||||||
|
updateObjProcess();
|
||||||
|
|
||||||
|
if(obj_read_progress == obj_read_prog_tot) {
|
||||||
|
updateObjComplete();
|
||||||
|
obj_reading = false;
|
||||||
|
|
||||||
|
triggerRender();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _path = getInputData(in_mesh + 0);
|
||||||
|
if(_path != current_path) updateObj(_path);
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static processData = function(_output, _data, _output_index, _array_index = 0) { #region
|
||||||
|
if(obj_reading) return noone;
|
||||||
|
|
||||||
|
var _flip = _data[in_mesh + 1];
|
||||||
|
|
||||||
|
if(object == noone) return noone;
|
||||||
|
var materials = [];
|
||||||
|
for( var i = input_fix_len, n = array_length(_data); i < n; i++ )
|
||||||
|
materials[i - input_fix_len] = _data[i];
|
||||||
|
|
||||||
|
var _object = getObject(_array_index);
|
||||||
|
_object.VF = global.VF_POS_NORM_TEX_COL;
|
||||||
|
_object.VB = object.VB;
|
||||||
|
_object.NVB = object.NVB;
|
||||||
|
_object.vertex = object.vertex;
|
||||||
|
_object.size = object.size;
|
||||||
|
_object.object_counts = object.object_counts;
|
||||||
|
_object.materials = materials;
|
||||||
|
_object.material_index = materialIndex;
|
||||||
|
_object.texture_flip = _flip;
|
||||||
|
|
||||||
|
setTransform(_object, _data);
|
||||||
|
return _object;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static getPreviewValues = function() { return array_safe_get_fast(all_inputs, in_mesh + 2, noone); }
|
||||||
|
|
||||||
|
static onDrawNodeOver = function(xx, yy, _mx, _my, _s, _hover, _focus) { #region
|
||||||
|
if(!obj_reading) return;
|
||||||
|
|
||||||
|
var cx = xx + w * _s / 2;
|
||||||
|
var cy = yy + h * _s / 2;
|
||||||
|
var rr = min(w - 32, h - 32) * _s / 2;
|
||||||
|
|
||||||
|
draw_set_color(COLORS._main_icon);
|
||||||
|
draw_arc(cx, cy, rr, current_time / 5, current_time / 5 + 90, 4 * _s, 90);
|
||||||
|
} #endregion
|
||||||
|
}
|
857
#backups/scripts/node_export/node_export.gml.backup0
Normal file
857
#backups/scripts/node_export/node_export.gml.backup0
Normal file
|
@ -0,0 +1,857 @@
|
||||||
|
// 2024-05-01 11:49:40
|
||||||
|
function Node_create_Export(_x, _y, _group = noone) { #region
|
||||||
|
var path = "";
|
||||||
|
if(!LOADING && !APPENDING && !CLONING) {
|
||||||
|
path = get_save_filename(@"Portable Network Graphics (.png)|*.png|
|
||||||
|
Joint Photographic Experts Group (.jpg)|*.jpg|
|
||||||
|
Graphics Interchange Format (.gif)|*.gif|
|
||||||
|
Animated WebP (.webp)|*.webp|
|
||||||
|
MPEG-4 (.mp4)|*.mp4",
|
||||||
|
"export");
|
||||||
|
|
||||||
|
key_release();
|
||||||
|
}
|
||||||
|
|
||||||
|
var node = new Node_Export(_x, _y, _group);
|
||||||
|
node.inputs[| 1].setValue(path);
|
||||||
|
node.extensionCheck();
|
||||||
|
|
||||||
|
//ds_list_add(PANEL_GRAPH.nodes_list, node);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
function exportAll() {
|
||||||
|
if(IS_RENDERING) return;
|
||||||
|
|
||||||
|
var key = ds_map_find_first(PROJECT.nodeMap);
|
||||||
|
|
||||||
|
repeat(ds_map_size(PROJECT.nodeMap)) {
|
||||||
|
var node = PROJECT.nodeMap[? key];
|
||||||
|
key = ds_map_find_next(PROJECT.nodeMap, key);
|
||||||
|
|
||||||
|
if(!node.active) continue;
|
||||||
|
if(!is_instanceof(node, Node_Export)) continue;
|
||||||
|
|
||||||
|
node.doInspectorAction();
|
||||||
|
}
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
enum NODE_EXPORT_FORMAT {
|
||||||
|
single,
|
||||||
|
sequence,
|
||||||
|
animation,
|
||||||
|
}
|
||||||
|
|
||||||
|
function Node_Export(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
|
||||||
|
name = "Export";
|
||||||
|
preview_channel = 1;
|
||||||
|
autoUpdatedTrigger = false;
|
||||||
|
|
||||||
|
playing = false;
|
||||||
|
played = 0;
|
||||||
|
|
||||||
|
_format_still = { filter: "Portable Network Graphics (.png)|*.png|Joint Photographic Experts Group (.jpg)|*.jpg" };
|
||||||
|
_format_anim = { filter: "Graphics Interchange Format (.gif)|*.gif|Animated WebP (.webp)|*.webp" };
|
||||||
|
|
||||||
|
inputs[| 0] = nodeValue("Surface", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone);
|
||||||
|
|
||||||
|
inputs[| 1] = nodeValue("Paths", self, JUNCTION_CONNECT.input, VALUE_TYPE.path, "")
|
||||||
|
.setDisplay(VALUE_DISPLAY.path_save, _format_still)
|
||||||
|
.setVisible(true);
|
||||||
|
|
||||||
|
inputs[| 2] = nodeValue("Template", self, JUNCTION_CONNECT.input, VALUE_TYPE.text, "%d%n")
|
||||||
|
.rejectArray();
|
||||||
|
inputs[| 2].editWidget.format = TEXT_AREA_FORMAT.path_template;
|
||||||
|
inputs[| 2].editWidget.auto_update = true;
|
||||||
|
|
||||||
|
format_single = ["Single image", "Image sequence", "Animation"];
|
||||||
|
format_array = ["Multiple images", "Image sequences", "Animation"];
|
||||||
|
|
||||||
|
inputs[| 3] = nodeValue("Type", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
|
||||||
|
.setDisplay(VALUE_DISPLAY.enum_scroll, { data: format_single, update_hover: false })
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
inputs[| 4] = nodeValue("Template guides", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
|
||||||
|
.setDisplay(VALUE_DISPLAY.label,
|
||||||
|
@"%d Directory
|
||||||
|
%1d Goes up 1 level
|
||||||
|
%n File name
|
||||||
|
%f Frame
|
||||||
|
%i Array index" );
|
||||||
|
|
||||||
|
inputs[| 5] = nodeValue("Loop", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true)
|
||||||
|
.setVisible(false)
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
inputs[| 6] = nodeValue("Frame optimization", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false)
|
||||||
|
.setVisible(false)
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
inputs[| 7] = nodeValue("Color merge", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.02)
|
||||||
|
.setDisplay(VALUE_DISPLAY.slider)
|
||||||
|
.setVisible(false)
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
inputs[| 8] = nodeValue("Framerate", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 30)
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
format_image = [ ".png", ".jpg", ".webp" ];
|
||||||
|
format_animation = [ ".gif", ".apng", ".webp", ".mp4" ];
|
||||||
|
|
||||||
|
inputs[| 9] = nodeValue("Format", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
|
||||||
|
.setDisplay(VALUE_DISPLAY.enum_scroll, { data: format_image, update_hover: false })
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
inputs[| 10] = nodeValue("Quality", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 23)
|
||||||
|
.setDisplay(VALUE_DISPLAY.slider, { range: [ 0, 100, 0.1 ] })
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
inputs[| 11] = nodeValue("Sequence begin", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0);
|
||||||
|
|
||||||
|
inputs[| 12] = nodeValue("Frame range", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, [0, -1])
|
||||||
|
.setDisplay(VALUE_DISPLAY.slider_range, { range: [0, TOTAL_FRAMES, 0.1] });
|
||||||
|
|
||||||
|
png_format = [ "INDEX4", "INDEX8", "Default (PNG32)" ];
|
||||||
|
inputs[| 13] = nodeValue("Subformat", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 2)
|
||||||
|
.setDisplay(VALUE_DISPLAY.enum_scroll, { data: png_format, update_hover: false });
|
||||||
|
|
||||||
|
inputs[| 14] = nodeValue("Frame step", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1);
|
||||||
|
|
||||||
|
inputs[| 15] = nodeValue("Custom Range", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false)
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
outputs[| 0] = nodeValue("Loop exit", self, JUNCTION_CONNECT.output, VALUE_TYPE.any, 0);
|
||||||
|
|
||||||
|
outputs[| 1] = nodeValue("Preview", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone)
|
||||||
|
.setVisible(false);
|
||||||
|
|
||||||
|
template_guide = [
|
||||||
|
["%d", "Directory"],
|
||||||
|
["%1d", "Goes up 1 level"],
|
||||||
|
["%n", "File name"],
|
||||||
|
["%f", "Frame"],
|
||||||
|
["%i", "Array index"],
|
||||||
|
];
|
||||||
|
export_template = new Inspector_Custom_Renderer(function(_x, _y, _w, _m, _hover, _focus) { #region
|
||||||
|
var _tx = _x + ui(10);
|
||||||
|
var _ty = _y;
|
||||||
|
var _tw = _w - ui(8);
|
||||||
|
|
||||||
|
var rawpath = getInputData(1);
|
||||||
|
if(is_array(rawpath)) rawpath = array_safe_get_fast(rawpath, 0, "");
|
||||||
|
|
||||||
|
var _ext = getInputData(9);
|
||||||
|
var path = pathString(rawpath);
|
||||||
|
var pathA = pathString(rawpath,, true);
|
||||||
|
path = string_replace(path, ".png", array_safe_get_fast(inputs[| 9].display_data.data, _ext, ""));
|
||||||
|
|
||||||
|
draw_set_text(f_p1, fa_left, fa_top, COLORS._main_text);
|
||||||
|
var _th = ui(12) + string_height_ext(path, -1, _tw - ui(16), true);
|
||||||
|
draw_sprite_stretched_ext(THEME.ui_panel_bg, 1, _tx, _ty, _tw, _th, COLORS.node_composite_bg_blend, 1);
|
||||||
|
|
||||||
|
var lw = 0;
|
||||||
|
var lx = _tx + ui(8);
|
||||||
|
var ly = _ty + ui(6);
|
||||||
|
|
||||||
|
draw_set_alpha(0.9);
|
||||||
|
for( var i = 0, n = array_length(pathA); i < n; i++ ) {
|
||||||
|
var _txt = pathA[i];
|
||||||
|
|
||||||
|
if(is_array(_txt)) {
|
||||||
|
switch(_txt[0]) {
|
||||||
|
case "d" : draw_set_color(COLORS.widget_text_dec_d); break;
|
||||||
|
case "n" : draw_set_color(COLORS.widget_text_dec_n); break;
|
||||||
|
case "f" : draw_set_color(COLORS.widget_text_dec_f); break;
|
||||||
|
case "i" : draw_set_color(COLORS.widget_text_dec_i); break;
|
||||||
|
case "ext" : draw_set_color(COLORS._main_text_sub); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_txt = _txt[1];
|
||||||
|
} else
|
||||||
|
draw_set_color(COLORS._main_text);
|
||||||
|
|
||||||
|
for( var j = 1; j <= string_length(_txt); j++ ) {
|
||||||
|
var ch = string_char_at(_txt, j);
|
||||||
|
var ww = string_width(ch);
|
||||||
|
|
||||||
|
if(lw + ww > _tw - ui(16)) {
|
||||||
|
lw = 0;
|
||||||
|
lx = _tx + ui(8);
|
||||||
|
ly += string_height("M");
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_text(lx, ly, ch);
|
||||||
|
|
||||||
|
lw += ww;
|
||||||
|
lx += ww;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_set_alpha(1);
|
||||||
|
|
||||||
|
var hh = _th + ui(116);
|
||||||
|
var _cy = _y + _th + ui(8);
|
||||||
|
for( var i = 0, n = array_length(template_guide); i < n; i++ ) {
|
||||||
|
var _yy = _cy + ui(20) * i;
|
||||||
|
|
||||||
|
draw_set_text(f_p1, fa_left, fa_top, COLORS._main_text_sub);
|
||||||
|
draw_text_add(_x + ui(16 + 16), _yy, template_guide[i][0]);
|
||||||
|
|
||||||
|
draw_set_text(f_p1, fa_right, fa_top, COLORS._main_text_sub);
|
||||||
|
draw_text_add(_x + _w - ui(4 + 16), _yy, template_guide[i][1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hh;
|
||||||
|
}); #endregion
|
||||||
|
|
||||||
|
input_display_list = [
|
||||||
|
["Export", false], 0, 1, 2, export_template,
|
||||||
|
["Format", false], 3, 9, 6, 7, 10, 13,
|
||||||
|
["Custom Range", true, 15], 12,
|
||||||
|
["Animation", false], 8, 5, 11, 14,
|
||||||
|
];
|
||||||
|
|
||||||
|
render_process_id = 0;
|
||||||
|
render_type = "";
|
||||||
|
render_target = "";
|
||||||
|
|
||||||
|
directory = TEMPDIR + string(irandom_range(100000, 999999));
|
||||||
|
converter = filepath_resolve(PREFERENCES.ImageMagick_path) + "convert.exe";
|
||||||
|
magick = filepath_resolve(PREFERENCES.ImageMagick_path) + "magick.exe";
|
||||||
|
webp = filepath_resolve(PREFERENCES.webp_path) + "webpmux.exe";
|
||||||
|
gifski = filepath_resolve(PREFERENCES.gifski_path) + "win/gifski.exe";
|
||||||
|
ffmpeg = filepath_resolve(PREFERENCES.ffmpeg_path) + "bin/ffmpeg.exe";
|
||||||
|
|
||||||
|
if(OS == os_windows) {
|
||||||
|
if(!file_exists_empty(converter) || !file_exists_empty(magick)) noti_warning($"No ImageMagick detected at {magick}, please make sure the installation is complete and ImageMagick path is set properly in preference.");
|
||||||
|
if(!file_exists_empty(webp)) noti_warning($"No webp detected at {webp}, please make sure the installation is complete and webp path is set properly in preference.");
|
||||||
|
if(!file_exists_empty(gifski)) noti_warning($"No gifski detected at {gifski}, please make sure the installation is complete and gifski path is set properly in preference.");
|
||||||
|
if(!file_exists_empty(ffmpeg)) noti_warning($"No FFmpeg detected at {ffmpeg}, please make sure the installation is complete and FFmpeg path is set properly in preference.");
|
||||||
|
} else if(OS == os_macosx) {
|
||||||
|
var check_convert = ExecutedProcessReadFromStandardOutput(shell_execute("convert", ""));
|
||||||
|
if(string_pos(check_convert, "not found")) noti_warning($"No ImageMagick installed, please install imagemagick with homebrew or use the provided 'mac-libraries-installer.command'.");
|
||||||
|
|
||||||
|
var check_webp = ExecutedProcessReadFromStandardOutput(shell_execute("webp", ""));
|
||||||
|
if(string_pos(check_webp, "not found")) noti_warning($"No webp installed, please install webp with homwbrew or use the provided 'mac-libraries-installer.command'.");
|
||||||
|
|
||||||
|
var check_ffmpeg = ExecutedProcessReadFromStandardOutput(shell_execute("ffmpeg", ""));
|
||||||
|
if(string_pos(check_ffmpeg, "not found")) noti_warning($"No FFmpeg installed, please install FFmpeg with homebrew or use the provided 'mac-libraries-installer.command'.");
|
||||||
|
|
||||||
|
var _opt = "/opt/homebrew/bin/";
|
||||||
|
converter = _opt + "convert";
|
||||||
|
magick = _opt + "magick";
|
||||||
|
webp = _opt + "webp";
|
||||||
|
ffmpeg = _opt + "ffmpeg";
|
||||||
|
}
|
||||||
|
|
||||||
|
static onValueUpdate = function(_index) { #region
|
||||||
|
var form = getInputData(3);
|
||||||
|
|
||||||
|
if(_index == 3) {
|
||||||
|
if(NOT_LOAD) inputs[| 9].setValue(0);
|
||||||
|
|
||||||
|
switch(form) {
|
||||||
|
case 0 :
|
||||||
|
case 1 :
|
||||||
|
inputs[| 1].display_data = _format_still;
|
||||||
|
break;
|
||||||
|
case 2 :
|
||||||
|
inputs[| 1].display_data = _format_anim;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(NOT_LOAD && _index == 3 && form == 1)
|
||||||
|
inputs[| 2].setValue("%d%n%3f%i");
|
||||||
|
|
||||||
|
if(NOT_LOAD && _index == 1) {
|
||||||
|
var _path = getInputData(1);
|
||||||
|
var _ext = filename_ext(_path);
|
||||||
|
|
||||||
|
switch(_ext) {
|
||||||
|
case ".png" : inputs[| 9].setValue(0); break;
|
||||||
|
case ".jpg" : inputs[| 9].setValue(1); break;
|
||||||
|
|
||||||
|
case ".gif" : inputs[| 9].setValue(0); break;
|
||||||
|
case ".webp" : inputs[| 9].setValue(1); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static extensionCheck = function() { #region
|
||||||
|
var _path = getInputData(1);
|
||||||
|
var _ext = filename_ext(_path);
|
||||||
|
|
||||||
|
switch(_ext) {
|
||||||
|
case ".png" :
|
||||||
|
inputs[| 3].setValue(0);
|
||||||
|
inputs[| 9].setValue(0);
|
||||||
|
break;
|
||||||
|
case ".jpg" :
|
||||||
|
inputs[| 3].setValue(0);
|
||||||
|
inputs[| 9].setValue(1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ".gif" :
|
||||||
|
inputs[| 3].setValue(2);
|
||||||
|
inputs[| 9].setValue(0);
|
||||||
|
break;
|
||||||
|
case ".webp" :
|
||||||
|
inputs[| 3].setValue(2);
|
||||||
|
inputs[| 9].setValue(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static renderWebp = function(temp_path, target_path) { #region
|
||||||
|
var _path = file_find_first(temp_path + "*.png", 0);
|
||||||
|
var frames = [];
|
||||||
|
|
||||||
|
while(_path != "") {
|
||||||
|
var _frame = string_quote(temp_path + string_replace_all(_path, ".png", "") + ".webp");
|
||||||
|
var _pathTemp = string_quote(temp_path + _path);
|
||||||
|
var shell_cmd = _pathTemp + " -define webp:lossless=true " + _frame;
|
||||||
|
|
||||||
|
array_push(frames, _frame);
|
||||||
|
shell_execute_async(magick, shell_cmd, self, false);
|
||||||
|
|
||||||
|
_path = file_find_next();
|
||||||
|
}
|
||||||
|
|
||||||
|
var rate = getInputData(8);
|
||||||
|
if(rate == 0) rate = 1;
|
||||||
|
|
||||||
|
var framerate = round(1 / rate * 1000);
|
||||||
|
var cmd = "";
|
||||||
|
|
||||||
|
for( var i = 0, n = array_length(frames); i < n; i++ )
|
||||||
|
cmd += $"-frame {frames[i]} +{framerate}+0+0+1 ";
|
||||||
|
|
||||||
|
cmd += "-bgcolor 0,0,0,0 ";
|
||||||
|
cmd += "-o " + string_quote(target_path);
|
||||||
|
|
||||||
|
render_process_id = shell_execute_async(webp, cmd, self);
|
||||||
|
render_type = "webp";
|
||||||
|
render_target = target_path;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static renderGif = function(temp_path, target_path) { #region
|
||||||
|
var loop = getInputData( 5);
|
||||||
|
var opti = getInputData( 6);
|
||||||
|
var fuzz = getInputData( 7);
|
||||||
|
var rate = getInputData( 8);
|
||||||
|
var qual = getInputData(10);
|
||||||
|
if(rate == 0) rate = 1;
|
||||||
|
|
||||||
|
temp_path = string_replace_all(temp_path, "/", "\\");
|
||||||
|
target_path = string_replace_all(target_path, "/", "\\");
|
||||||
|
|
||||||
|
var framerate = 100 / rate;
|
||||||
|
var loop_str = loop? 0 : 1;
|
||||||
|
var use_gifski = false;
|
||||||
|
|
||||||
|
var shell_cmd = $"-delay {framerate} -alpha set -dispose 2 -loop {loop_str}";
|
||||||
|
if(opti) shell_cmd += $" -fuzz {fuzz * 100}% -layers OptimizeFrame -layers OptimizeTransparency";
|
||||||
|
shell_cmd += $" {string_quote(temp_path)} {string_quote(target_path)}";
|
||||||
|
|
||||||
|
render_process_id = shell_execute_async(converter, shell_cmd, self);
|
||||||
|
render_type = "gif";
|
||||||
|
render_target = target_path;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static renderMp4 = function(temp_path, target_path) { #region
|
||||||
|
var rate = getInputData( 8);
|
||||||
|
var qual = getInputData(10); qual = clamp(qual, 0, 51);
|
||||||
|
if(rate == 0) rate = 1;
|
||||||
|
|
||||||
|
if(file_exists_empty(target_path)) file_delete(target_path);
|
||||||
|
|
||||||
|
temp_path = string_replace_all(temp_path, "/", "\\");
|
||||||
|
target_path = string_replace_all(target_path, "/", "\\");
|
||||||
|
|
||||||
|
var shell_cmd = $"-hide_banner -loglevel quiet -framerate {rate} -i \"{temp_path}%05d.png\" -c:v libx264 -r {rate} -pix_fmt yuv420p -crf {qual} {string_quote(target_path)}";
|
||||||
|
|
||||||
|
render_process_id = shell_execute_async(ffmpeg, shell_cmd, self);
|
||||||
|
render_type = "mp4";
|
||||||
|
render_target = target_path;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static renderApng = function(temp_path, target_path) { #region
|
||||||
|
var rate = getInputData( 8);
|
||||||
|
if(rate == 0) rate = 1;
|
||||||
|
|
||||||
|
if(file_exists_empty(target_path)) file_delete(target_path);
|
||||||
|
|
||||||
|
temp_path = string_replace_all(temp_path, "/", "\\");
|
||||||
|
target_path = string_replace_all(target_path, "/", "\\");
|
||||||
|
|
||||||
|
var shell_cmd = $"-hide_banner -loglevel quiet -framerate {rate} -i \"{temp_path}%05d.png\" -plays 0 {string_quote(target_path)}";
|
||||||
|
|
||||||
|
render_process_id = shell_execute_async(ffmpeg, shell_cmd, self);
|
||||||
|
render_type = "apng";
|
||||||
|
render_target = target_path;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static pathString = function(path, index = 0, _array = false) { #region
|
||||||
|
var suff = getInputData( 2);
|
||||||
|
var form = getInputData( 3);
|
||||||
|
var strt = getInputData(11);
|
||||||
|
|
||||||
|
path = string_replace_all(path, "\\", "/");
|
||||||
|
|
||||||
|
var s = _array? [] : "";
|
||||||
|
var i = 1;
|
||||||
|
var ch, ch_s;
|
||||||
|
var len = string_length(suff);
|
||||||
|
|
||||||
|
while(i <= len) {
|
||||||
|
ch = string_char_at(suff, i);
|
||||||
|
|
||||||
|
if(ch == "%") {
|
||||||
|
i++;
|
||||||
|
var res = false, str = "";
|
||||||
|
|
||||||
|
do {
|
||||||
|
ch_s = string_char_at(suff, i);
|
||||||
|
switch(ch_s) {
|
||||||
|
case "f" :
|
||||||
|
var _txt = "";
|
||||||
|
var float_str = string_digits(str);
|
||||||
|
if(float_str != "") {
|
||||||
|
var float_val = string_digits(float_str);
|
||||||
|
var str_val = max(float_val - string_length(string(CURRENT_FRAME + 1 + strt)), 0);
|
||||||
|
repeat(str_val)
|
||||||
|
_txt += "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
_txt += string(CURRENT_FRAME + 1 + strt);
|
||||||
|
if(_array) array_push(s, [ "f", _txt ]);
|
||||||
|
else s += _txt;
|
||||||
|
res = true;
|
||||||
|
break;
|
||||||
|
case "i" :
|
||||||
|
var _txt = "";
|
||||||
|
var float_str = string_digits(str);
|
||||||
|
if(float_str != "") {
|
||||||
|
var float_val = string_digits(float_str);
|
||||||
|
var str_val = max(float_val - string_length(string(index)), 0);
|
||||||
|
repeat(str_val)
|
||||||
|
_txt += "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
_txt += string(index);
|
||||||
|
if(_array) array_push(s, [ "i", _txt ]);
|
||||||
|
else s += _txt;
|
||||||
|
res = true;
|
||||||
|
break;
|
||||||
|
case "d" :
|
||||||
|
var dir = filename_dir(path) + "/";
|
||||||
|
var _txt = "";
|
||||||
|
|
||||||
|
var float_str = string_digits(str);
|
||||||
|
if(float_str != "") {
|
||||||
|
var float_val = toNumber(string_digits(float_str)) + 1;
|
||||||
|
var dir_s = "";
|
||||||
|
var sep = string_splice(dir, "/");
|
||||||
|
|
||||||
|
for(var j = 0; j < array_length(sep) - float_val; j++)
|
||||||
|
dir_s += sep[j] + "/";
|
||||||
|
_txt += dir_s;
|
||||||
|
} else
|
||||||
|
_txt += dir;
|
||||||
|
|
||||||
|
if(_array) array_push(s, [ "d", _txt ]);
|
||||||
|
else s += _txt;
|
||||||
|
res = true;
|
||||||
|
break;
|
||||||
|
case "n" :
|
||||||
|
var ext = filename_ext(path);
|
||||||
|
var _txt = string_replace(filename_name(path), ext, "");
|
||||||
|
|
||||||
|
if(_array) array_push(s, [ "n", _txt ]);
|
||||||
|
else s += _txt;
|
||||||
|
res = true;
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
str += ch_s;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
} until(i > string_length(suff) || res);
|
||||||
|
} else {
|
||||||
|
if(_array) array_push(s, ch);
|
||||||
|
else s += ch;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _e = getInputData(9);
|
||||||
|
var _ext = array_safe_get_fast(inputs[| 9].display_data.data, _e, ".png");
|
||||||
|
|
||||||
|
if(_array) array_push(s, ["ext", _ext]);
|
||||||
|
else s += _ext;
|
||||||
|
|
||||||
|
return s;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static save_surface = function(_surf, _path) { #region
|
||||||
|
var form = getInputData(3);
|
||||||
|
//print($">>>>>>>>>>>>>>>>>>>> save surface {_surf} - {_path} <<<<<<<<<<<<<<<<<<<<");
|
||||||
|
|
||||||
|
if(form == NODE_EXPORT_FORMAT.animation) {
|
||||||
|
surface_save_safe(_surf, _path);
|
||||||
|
return _path;
|
||||||
|
}
|
||||||
|
|
||||||
|
var extd = getInputData( 9);
|
||||||
|
var qual = getInputData(10);
|
||||||
|
var indx = getInputData(13);
|
||||||
|
var ext = array_safe_get_fast(format_image, extd, ".png");
|
||||||
|
|
||||||
|
var _pathOut = _path;
|
||||||
|
var _pathTemp = $"{directory}/{irandom_range(10000, 99999)}.png";
|
||||||
|
|
||||||
|
switch(ext) {
|
||||||
|
case ".png":
|
||||||
|
switch(indx) {
|
||||||
|
case 0 :
|
||||||
|
surface_save_safe(_surf, _pathTemp);
|
||||||
|
|
||||||
|
var shell_cmd = $"convert {string_quote(_pathTemp)} {string_quote(_pathOut)}";
|
||||||
|
shell_execute_async(magick, shell_cmd, self);
|
||||||
|
break;
|
||||||
|
case 1 :
|
||||||
|
surface_save_safe(_surf, _pathTemp);
|
||||||
|
|
||||||
|
var shell_cmd = $"convert {string_quote(_pathTemp)} PNG8:{string_quote(_pathOut)}";
|
||||||
|
shell_execute_async(magick, shell_cmd, self);
|
||||||
|
break;
|
||||||
|
case 2 :
|
||||||
|
surface_save_safe(_surf, _pathOut);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ".jpg":
|
||||||
|
surface_save_safe(_surf, _pathTemp);
|
||||||
|
|
||||||
|
_pathOut = $"\"{string_replace_all(_path, ".png", "")}.jpg\"";
|
||||||
|
var shell_cmd = $"{string_quote(_pathTemp)} -quality {qual} {string_quote(_pathOut)}";
|
||||||
|
|
||||||
|
shell_execute_async(magick, shell_cmd, self);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ".webp":
|
||||||
|
surface_save_safe(_surf, _pathTemp);
|
||||||
|
|
||||||
|
_pathOut = $"\"{string_replace_all(_path, ".png", "")}.webp\"";
|
||||||
|
var shell_cmd = $"{string_quote(_pathTemp)} -quality {qual} -define webp:lossless=true {string_quote(_pathOut)}";
|
||||||
|
|
||||||
|
shell_execute_async(magick, shell_cmd, self);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _pathOut;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static export = function() { #region
|
||||||
|
//print($">>>>>>>>>>>>>>>>>>>> export {CURRENT_FRAME} <<<<<<<<<<<<<<<<<<<<");
|
||||||
|
|
||||||
|
var surf = getInputData( 0);
|
||||||
|
var path = getInputData( 1);
|
||||||
|
var suff = getInputData( 2);
|
||||||
|
var form = getInputData( 3);
|
||||||
|
var rang = getInputData(12);
|
||||||
|
var stps = getInputData(14);
|
||||||
|
var user = getInputData(15);
|
||||||
|
|
||||||
|
if(form >= 1 && user) {
|
||||||
|
var rng_s = rang[0];
|
||||||
|
var rng_e = rang[1];
|
||||||
|
var rng_st = stps >= 1? (CURRENT_FRAME - rng_s) % stps : 0;
|
||||||
|
|
||||||
|
if(CURRENT_FRAME < rng_s - 1) return;
|
||||||
|
if(CURRENT_FRAME > rng_e - 1) return;
|
||||||
|
if(rng_st != 0) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_array(surf)) {
|
||||||
|
var p = "";
|
||||||
|
for(var i = 0; i < array_length(surf); i++) {
|
||||||
|
var _surf = surf[i];
|
||||||
|
if(!is_surface(_surf)) continue;
|
||||||
|
|
||||||
|
if(form == NODE_EXPORT_FORMAT.animation) {
|
||||||
|
p = $"{directory}/{i}/{string_lead_zero(CURRENT_FRAME, 5)}.png";
|
||||||
|
} else {
|
||||||
|
if(is_array(path) && array_length(path) == array_length(surf))
|
||||||
|
p = pathString(array_safe_get_fast(path, i), i);
|
||||||
|
else
|
||||||
|
p = pathString(path, i);
|
||||||
|
CLI_EXPORT_AMOUNT++;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = save_surface(_surf, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(form != NODE_EXPORT_FORMAT.animation && !IS_CMD) {
|
||||||
|
var noti = log_message("EXPORT", $"Export {array_length(surf)} images complete.", THEME.noti_icon_tick, COLORS._main_value_positive, false);
|
||||||
|
noti.path = filename_dir(p);
|
||||||
|
noti.setOnClick(function() { shellOpenExplorer(self.path); }, "Open in explorer", THEME.explorer);
|
||||||
|
|
||||||
|
PANEL_MENU.setNotiIcon(THEME.noti_icon_tick);
|
||||||
|
}
|
||||||
|
} else if(is_surface(surf)) {
|
||||||
|
var p = path;
|
||||||
|
if(is_array(path)) p = path[0];
|
||||||
|
|
||||||
|
if(form == NODE_EXPORT_FORMAT.animation) {
|
||||||
|
p = $"{directory}/{string_lead_zero(CURRENT_FRAME, 5)}.png";
|
||||||
|
} else {
|
||||||
|
p = pathString(p);
|
||||||
|
CLI_EXPORT_AMOUNT++;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = save_surface(surf, p);
|
||||||
|
|
||||||
|
if(form != NODE_EXPORT_FORMAT.animation && !IS_CMD) {
|
||||||
|
var noti = log_message("EXPORT", $"Export image as {p}", THEME.noti_icon_tick, COLORS._main_value_positive, false);
|
||||||
|
noti.path = filename_dir(p);
|
||||||
|
noti.setOnClick(function() { shellOpenExplorer(self.path); }, "Open in explorer", THEME.explorer);
|
||||||
|
|
||||||
|
PANEL_MENU.setNotiIcon(THEME.noti_icon_tick);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static renderCompleted = function() { #region
|
||||||
|
var surf = getInputData( 0);
|
||||||
|
var path = getInputData( 1);
|
||||||
|
var suff = getInputData( 2);
|
||||||
|
var extd = getInputData( 9);
|
||||||
|
var temp_path, target_path;
|
||||||
|
|
||||||
|
update_on_frame = false;
|
||||||
|
|
||||||
|
if(is_array(surf)) {
|
||||||
|
for(var i = 0; i < array_length(surf); i++) {
|
||||||
|
temp_path = $"{directory}/{i}/*.png";
|
||||||
|
if(is_array(path)) target_path = pathString(array_safe_get_fast(path, i), i);
|
||||||
|
else target_path = pathString(path, i);
|
||||||
|
|
||||||
|
switch(format_animation[extd]) {
|
||||||
|
case ".gif" :
|
||||||
|
target_path = string_replace(target_path, ".png", ".gif");
|
||||||
|
renderGif(temp_path, target_path);
|
||||||
|
break;
|
||||||
|
case ".webp" :
|
||||||
|
target_path = string_replace(target_path, ".png", ".webp");
|
||||||
|
renderWebp(temp_path, target_path);
|
||||||
|
break;
|
||||||
|
case ".mp4" :
|
||||||
|
target_path = string_replace(target_path, ".png", ".mp4");
|
||||||
|
renderMp4(temp_path, target_path);
|
||||||
|
break;
|
||||||
|
case ".apng" :
|
||||||
|
target_path = string_replace(target_path, ".png", ".apng");
|
||||||
|
renderApng(temp_path, target_path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
target_path = pathString(path);
|
||||||
|
|
||||||
|
switch(format_animation[extd]) {
|
||||||
|
case ".gif" :
|
||||||
|
target_path = string_replace(target_path, ".png", ".gif");
|
||||||
|
renderGif(directory + "/*.png", target_path);
|
||||||
|
break;
|
||||||
|
case ".webp" :
|
||||||
|
target_path = string_replace(target_path, ".png", ".webp");
|
||||||
|
renderWebp(directory + "/", target_path);
|
||||||
|
break;
|
||||||
|
case ".mp4" :
|
||||||
|
target_path = string_replace(target_path, ".png", ".mp4");
|
||||||
|
renderMp4(directory + "/", target_path);
|
||||||
|
break;
|
||||||
|
case ".apng" :
|
||||||
|
target_path = string_replace(target_path, ".png", ".apng");
|
||||||
|
renderApng(directory + "/", target_path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedOutTrigger.setValue(true);
|
||||||
|
CLI_EXPORT_AMOUNT++;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
insp1UpdateTooltip = "Export";
|
||||||
|
insp1UpdateIcon = [ THEME.sequence_control, 1, COLORS._main_value_positive ];
|
||||||
|
|
||||||
|
insp2UpdateTooltip = "Export All";
|
||||||
|
insp2UpdateIcon = [ THEME.play_all, 0, COLORS._main_value_positive ];
|
||||||
|
|
||||||
|
static onInspector1Update = function() { #region
|
||||||
|
if(IS_RENDERING) return;
|
||||||
|
|
||||||
|
if(isInLoop()) RENDER_ALL
|
||||||
|
else doInspectorAction();
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static onInspector2Update = function() { #region
|
||||||
|
if(IS_RENDERING) return;
|
||||||
|
exportAll();
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static doInspectorAction = function() { #region
|
||||||
|
if(!IS_CMD && (LOADING || APPENDING)) return;
|
||||||
|
|
||||||
|
var path = getInputData(1);
|
||||||
|
if(path == "") return;
|
||||||
|
var form = getInputData(3);
|
||||||
|
|
||||||
|
if(form == NODE_EXPORT_FORMAT.single) {
|
||||||
|
Render();
|
||||||
|
|
||||||
|
export();
|
||||||
|
updatedOutTrigger.setValue(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
update_on_frame = true;
|
||||||
|
playing = true;
|
||||||
|
played = 0;
|
||||||
|
|
||||||
|
PROJECT.animator.render();
|
||||||
|
|
||||||
|
if(IS_CMD) array_push(PROGRAM_ARGUMENTS._exporting, node_id);
|
||||||
|
|
||||||
|
if(directory_exists(directory))
|
||||||
|
directory_destroy(directory);
|
||||||
|
directory_create(directory);
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static step = function() { #region
|
||||||
|
insp1UpdateActive = !IS_RENDERING;
|
||||||
|
insp2UpdateActive = !IS_RENDERING;
|
||||||
|
|
||||||
|
var surf = getInputData( 0);
|
||||||
|
var pngf = getInputData(13);
|
||||||
|
|
||||||
|
if(is_array(surf)) {
|
||||||
|
inputs[| 3].display_data.data = format_array;
|
||||||
|
inputs[| 3].editWidget.data_list = format_array;
|
||||||
|
} else {
|
||||||
|
inputs[| 3].display_data.data = format_single;
|
||||||
|
inputs[| 3].editWidget.data_list = format_single;
|
||||||
|
}
|
||||||
|
|
||||||
|
outputs[| 1].setValue(surf);
|
||||||
|
|
||||||
|
var anim = getInputData(3); // single, sequence, animation
|
||||||
|
var extn = getInputData(9);
|
||||||
|
var user = getInputData(15);
|
||||||
|
|
||||||
|
inputs[| 11].setVisible(anim == 1);
|
||||||
|
|
||||||
|
inputs[| 12].editWidget.minn = FIRST_FRAME + 1;
|
||||||
|
inputs[| 12].editWidget.maxx = LAST_FRAME + 1;
|
||||||
|
if(!user) inputs[| 12].setValueDirect([ FIRST_FRAME + 1, LAST_FRAME + 1], noone, false, 0, false);
|
||||||
|
|
||||||
|
inputs[| 14].setVisible(anim > 0);
|
||||||
|
|
||||||
|
if(anim == NODE_EXPORT_FORMAT.animation) {
|
||||||
|
var _fmt = array_safe_get_fast(format_animation, extn);
|
||||||
|
|
||||||
|
inputs[| 5].setVisible(_fmt == ".gif");
|
||||||
|
inputs[| 6].setVisible(_fmt == ".gif");
|
||||||
|
inputs[| 7].setVisible(_fmt == ".gif");
|
||||||
|
inputs[| 8].setVisible(true);
|
||||||
|
|
||||||
|
inputs[| 9].display_data.data = format_animation;
|
||||||
|
inputs[| 9].editWidget.data_list = format_animation;
|
||||||
|
|
||||||
|
inputs[| 13].setVisible(false);
|
||||||
|
|
||||||
|
if(_fmt == ".mp4") {
|
||||||
|
inputs[| 10].setName("CRF value");
|
||||||
|
inputs[| 10].tooltip = "Quality of the output, with 0 being the highest (and largest file size), and 51 being the lowest.";
|
||||||
|
|
||||||
|
inputs[| 10].setVisible(true);
|
||||||
|
inputs[| 10].editWidget.minn = 0;
|
||||||
|
inputs[| 10].editWidget.maxx = 51;
|
||||||
|
} else
|
||||||
|
inputs[| 10].setVisible(false);
|
||||||
|
} else {
|
||||||
|
var _fmt = array_safe_get_fast(format_image, extn);
|
||||||
|
|
||||||
|
inputs[| 5].setVisible(false);
|
||||||
|
inputs[| 6].setVisible(false);
|
||||||
|
inputs[| 7].setVisible(false);
|
||||||
|
inputs[| 8].setVisible(false);
|
||||||
|
|
||||||
|
inputs[| 9].display_data.data = format_image;
|
||||||
|
inputs[| 9].editWidget.data_list = format_image;
|
||||||
|
|
||||||
|
inputs[| 13].setVisible(_fmt == ".png");
|
||||||
|
|
||||||
|
if(_fmt == ".jpg" || _fmt == ".webp") {
|
||||||
|
inputs[| 10].setName("Quality");
|
||||||
|
inputs[| 10].tooltip = "Quality of the output.";
|
||||||
|
|
||||||
|
inputs[| 10].setVisible(true);
|
||||||
|
inputs[| 10].editWidget.minn = 0;
|
||||||
|
inputs[| 10].editWidget.maxx = 100;
|
||||||
|
} else
|
||||||
|
inputs[| 10].setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
outputs[| 0].visible = isInLoop();
|
||||||
|
|
||||||
|
if(render_process_id != 0) {
|
||||||
|
var res = ProcIdExists(render_process_id);
|
||||||
|
|
||||||
|
if(res == 0 || OS == os_macosx) {
|
||||||
|
if(!IS_CMD) {
|
||||||
|
var noti = log_message("EXPORT", $"Export {render_type} as {render_target}", THEME.noti_icon_tick, COLORS._main_value_positive, false);
|
||||||
|
noti.path = filename_dir(render_target);
|
||||||
|
noti.setOnClick(function() { shellOpenExplorer(self.path); }, "Open in explorer", THEME.explorer);
|
||||||
|
PANEL_MENU.setNotiIcon(THEME.noti_icon_tick);
|
||||||
|
}
|
||||||
|
|
||||||
|
render_process_id = 0;
|
||||||
|
|
||||||
|
if(IS_CMD) array_remove(PROGRAM_ARGUMENTS._exporting, node_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static update = function(frame = CURRENT_FRAME) { #region
|
||||||
|
var anim = getInputData(3);
|
||||||
|
if(anim == NODE_EXPORT_FORMAT.single) {
|
||||||
|
if(isInLoop()) export();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!PROJECT.animator.is_playing) {
|
||||||
|
playing = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!playing) return;
|
||||||
|
|
||||||
|
export();
|
||||||
|
|
||||||
|
if(IS_LAST_FRAME && anim == NODE_EXPORT_FORMAT.animation)
|
||||||
|
renderCompleted();
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) { #region
|
||||||
|
graph_preview_alpha = 1;
|
||||||
|
if(render_process_id != 0) {
|
||||||
|
graph_preview_alpha = 0.5;
|
||||||
|
draw_sprite_ui(THEME.loading, 0, xx + w * _s / 2, yy + h * _s / 2, _s, _s, current_time / 2, COLORS._main_icon, 1);
|
||||||
|
}
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static doApplyDeserialize = function() { onValueUpdate(3); }
|
||||||
|
}
|
857
#backups/scripts/node_export/node_export.gml.backup1
Normal file
857
#backups/scripts/node_export/node_export.gml.backup1
Normal file
|
@ -0,0 +1,857 @@
|
||||||
|
// 2024-05-01 11:49:13
|
||||||
|
function Node_create_Export(_x, _y, _group = noone) { #region
|
||||||
|
var path = "";
|
||||||
|
if(!LOADING && !APPENDING && !CLONING) {
|
||||||
|
path = get_save_filename(@"Portable Network Graphics (.png)|*.png|
|
||||||
|
Joint Photographic Experts Group (.jpg)|*.jpg|
|
||||||
|
Graphics Interchange Format (.gif)|*.gif|
|
||||||
|
Animated WebP (.webp)|*.webp|
|
||||||
|
MPEG-4 (.mp4)|*.mp4",
|
||||||
|
"export");
|
||||||
|
|
||||||
|
key_release();
|
||||||
|
}
|
||||||
|
|
||||||
|
var node = new Node_Export(_x, _y, _group);
|
||||||
|
node.inputs[| 1].setValue(path);
|
||||||
|
node.extensionCheck();
|
||||||
|
|
||||||
|
//ds_list_add(PANEL_GRAPH.nodes_list, node);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
function exportAll() {
|
||||||
|
if(IS_RENDERING) return;
|
||||||
|
|
||||||
|
var key = ds_map_find_first(PROJECT.nodeMap);
|
||||||
|
|
||||||
|
repeat(ds_map_size(PROJECT.nodeMap)) {
|
||||||
|
var node = PROJECT.nodeMap[? key];
|
||||||
|
key = ds_map_find_next(PROJECT.nodeMap, key);
|
||||||
|
|
||||||
|
if(!node.active) continue;
|
||||||
|
if(!is_instanceof(node, Node_Export)) continue;
|
||||||
|
|
||||||
|
node.doInspectorAction();
|
||||||
|
}
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
enum NODE_EXPORT_FORMAT {
|
||||||
|
single,
|
||||||
|
sequence,
|
||||||
|
animation,
|
||||||
|
}
|
||||||
|
|
||||||
|
function Node_Export(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
|
||||||
|
name = "Export";
|
||||||
|
preview_channel = 1;
|
||||||
|
autoUpdatedTrigger = false;
|
||||||
|
|
||||||
|
playing = false;
|
||||||
|
played = 0;
|
||||||
|
|
||||||
|
_format_still = { filter: "Portable Network Graphics (.png)|*.png|Joint Photographic Experts Group (.jpg)|*.jpg" };
|
||||||
|
_format_anim = { filter: "Graphics Interchange Format (.gif)|*.gif|Animated WebP (.webp)|*.webp" };
|
||||||
|
|
||||||
|
inputs[| 0] = nodeValue("Surface", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone);
|
||||||
|
|
||||||
|
inputs[| 1] = nodeValue("Paths", self, JUNCTION_CONNECT.input, VALUE_TYPE.path, "")
|
||||||
|
.setDisplay(VALUE_DISPLAY.path_save, _format_still)
|
||||||
|
.setVisible(true);
|
||||||
|
|
||||||
|
inputs[| 2] = nodeValue("Template", self, JUNCTION_CONNECT.input, VALUE_TYPE.text, "%d%n")
|
||||||
|
.rejectArray();
|
||||||
|
inputs[| 2].editWidget.format = TEXT_AREA_FORMAT.path_template;
|
||||||
|
inputs[| 2].editWidget.auto_update = true;
|
||||||
|
|
||||||
|
format_single = ["Single image", "Image sequence", "Animation"];
|
||||||
|
format_array = ["Multiple images", "Image sequences", "Animation"];
|
||||||
|
|
||||||
|
inputs[| 3] = nodeValue("Type", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
|
||||||
|
.setDisplay(VALUE_DISPLAY.enum_scroll, { data: format_single, update_hover: false })
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
inputs[| 4] = nodeValue("Template guides", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
|
||||||
|
.setDisplay(VALUE_DISPLAY.label,
|
||||||
|
@"%d Directory
|
||||||
|
%1d Goes up 1 level
|
||||||
|
%n File name
|
||||||
|
%f Frame
|
||||||
|
%i Array index" );
|
||||||
|
|
||||||
|
inputs[| 5] = nodeValue("Loop", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true)
|
||||||
|
.setVisible(false)
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
inputs[| 6] = nodeValue("Frame optimization", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false)
|
||||||
|
.setVisible(false)
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
inputs[| 7] = nodeValue("Color merge", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.02)
|
||||||
|
.setDisplay(VALUE_DISPLAY.slider)
|
||||||
|
.setVisible(false)
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
inputs[| 8] = nodeValue("Framerate", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 30)
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
format_image = [ ".png", ".jpg", ".webp" ];
|
||||||
|
format_animation = [ ".gif", ".apng", ".webp", ".mp4" ];
|
||||||
|
|
||||||
|
inputs[| 9] = nodeValue("Format", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
|
||||||
|
.setDisplay(VALUE_DISPLAY.enum_scroll, { data: format_image, update_hover: false })
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
inputs[| 10] = nodeValue("Quality", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 23)
|
||||||
|
.setDisplay(VALUE_DISPLAY.slider, { range: [ 0, 100, 0.1 ] })
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
inputs[| 11] = nodeValue("Sequence begin", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0);
|
||||||
|
|
||||||
|
inputs[| 12] = nodeValue("Frame range", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, [0, -1])
|
||||||
|
.setDisplay(VALUE_DISPLAY.slider_range, { range: [0, TOTAL_FRAMES, 0.1] });
|
||||||
|
|
||||||
|
png_format = [ "INDEX4", "INDEX8", "Default (PNG32)" ];
|
||||||
|
inputs[| 13] = nodeValue("Subformat", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 2)
|
||||||
|
.setDisplay(VALUE_DISPLAY.enum_scroll, { data: png_format, update_hover: false });
|
||||||
|
|
||||||
|
inputs[| 14] = nodeValue("Frame step", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1);
|
||||||
|
|
||||||
|
inputs[| 15] = nodeValue("Custom Range", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false)
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
|
outputs[| 0] = nodeValue("Loop exit", self, JUNCTION_CONNECT.output, VALUE_TYPE.any, 0);
|
||||||
|
|
||||||
|
outputs[| 1] = nodeValue("Preview", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone)
|
||||||
|
.setVisible(false);
|
||||||
|
|
||||||
|
template_guide = [
|
||||||
|
["%d", "Directory"],
|
||||||
|
["%1d", "Goes up 1 level"],
|
||||||
|
["%n", "File name"],
|
||||||
|
["%f", "Frame"],
|
||||||
|
["%i", "Array index"],
|
||||||
|
];
|
||||||
|
export_template = new Inspector_Custom_Renderer(function(_x, _y, _w, _m, _hover, _focus) { #region
|
||||||
|
var _tx = _x + ui(10);
|
||||||
|
var _ty = _y;
|
||||||
|
var _tw = _w - ui(8);
|
||||||
|
|
||||||
|
var rawpath = getInputData(1);
|
||||||
|
if(is_array(rawpath)) rawpath = array_safe_get_fast(rawpath, 0, "");
|
||||||
|
|
||||||
|
var _ext = getInputData(9);
|
||||||
|
var path = pathString(rawpath);
|
||||||
|
var pathA = pathString(rawpath,, true);
|
||||||
|
path = string_replace(path, ".png", array_safe_get_fast(inputs[| 9].display_data.data, _ext, ""));
|
||||||
|
|
||||||
|
draw_set_text(f_p1, fa_left, fa_top, COLORS._main_text);
|
||||||
|
var _th = ui(12) + string_height_ext(path, -1, _tw - ui(16), true);
|
||||||
|
draw_sprite_stretched_ext(THEME.ui_panel_bg, 1, _tx, _ty, _tw, _th, COLORS.node_composite_bg_blend, 1);
|
||||||
|
|
||||||
|
var lw = 0;
|
||||||
|
var lx = _tx + ui(8);
|
||||||
|
var ly = _ty + ui(6);
|
||||||
|
|
||||||
|
draw_set_alpha(0.9);
|
||||||
|
for( var i = 0, n = array_length(pathA); i < n; i++ ) {
|
||||||
|
var _txt = pathA[i];
|
||||||
|
|
||||||
|
if(is_array(_txt)) {
|
||||||
|
switch(_txt[0]) {
|
||||||
|
case "d" : draw_set_color(COLORS.widget_text_dec_d); break;
|
||||||
|
case "n" : draw_set_color(COLORS.widget_text_dec_n); break;
|
||||||
|
case "f" : draw_set_color(COLORS.widget_text_dec_f); break;
|
||||||
|
case "i" : draw_set_color(COLORS.widget_text_dec_i); break;
|
||||||
|
case "ext" : draw_set_color(COLORS._main_text_sub); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_txt = _txt[1];
|
||||||
|
} else
|
||||||
|
draw_set_color(COLORS._main_text);
|
||||||
|
|
||||||
|
for( var j = 1; j <= string_length(_txt); j++ ) {
|
||||||
|
var ch = string_char_at(_txt, j);
|
||||||
|
var ww = string_width(ch);
|
||||||
|
|
||||||
|
if(lw + ww > _tw - ui(16)) {
|
||||||
|
lw = 0;
|
||||||
|
lx = _tx + ui(8);
|
||||||
|
ly += string_height("M");
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_text(lx, ly, ch);
|
||||||
|
|
||||||
|
lw += ww;
|
||||||
|
lx += ww;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_set_alpha(1);
|
||||||
|
|
||||||
|
var hh = _th + ui(116);
|
||||||
|
var _cy = _y + _th + ui(8);
|
||||||
|
for( var i = 0, n = array_length(template_guide); i < n; i++ ) {
|
||||||
|
var _yy = _cy + ui(20) * i;
|
||||||
|
|
||||||
|
draw_set_text(f_p1, fa_left, fa_top, COLORS._main_text_sub);
|
||||||
|
draw_text_add(_x + ui(16 + 16), _yy, template_guide[i][0]);
|
||||||
|
|
||||||
|
draw_set_text(f_p1, fa_right, fa_top, COLORS._main_text_sub);
|
||||||
|
draw_text_add(_x + _w - ui(4 + 16), _yy, template_guide[i][1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hh;
|
||||||
|
}); #endregion
|
||||||
|
|
||||||
|
input_display_list = [
|
||||||
|
["Export", false], 0, 1, 2, export_template,
|
||||||
|
["Format", false], 3, 9, 6, 7, 10, 13,
|
||||||
|
["Custom Range", true, 15], 12,
|
||||||
|
["Animation", false], 8, 5, 11, 14,
|
||||||
|
];
|
||||||
|
|
||||||
|
render_process_id = 0;
|
||||||
|
render_type = "";
|
||||||
|
render_target = "";
|
||||||
|
|
||||||
|
directory = TEMPDIR + string(irandom_range(100000, 999999));
|
||||||
|
converter = filepath_resolve(PREFERENCES.ImageMagick_path) + "convert.exe";
|
||||||
|
magick = filepath_resolve(PREFERENCES.ImageMagick_path) + "magick.exe";
|
||||||
|
webp = filepath_resolve(PREFERENCES.webp_path) + "webpmux.exe";
|
||||||
|
gifski = filepath_resolve(PREFERENCES.gifski_path) + "win/gifski.exe";
|
||||||
|
ffmpeg = filepath_resolve(PREFERENCES.ffmpeg_path) + "bin/ffmpeg.exe";
|
||||||
|
|
||||||
|
if(OS == os_windows) {
|
||||||
|
if(!file_exists_empty(converter) || !file_exists_empty(magick)) noti_warning($"No ImageMagick detected at {magick}, please make sure the installation is complete and ImageMagick path is set properly in preference.");
|
||||||
|
if(!file_exists_empty(webp)) noti_warning($"No webp detected at {webp}, please make sure the installation is complete and webp path is set properly in preference.");
|
||||||
|
if(!file_exists_empty(gifski)) noti_warning($"No gifski detected at {gifski}, please make sure the installation is complete and gifski path is set properly in preference.");
|
||||||
|
if(!file_exists_empty(ffmpeg)) noti_warning($"No FFmpeg detected at {ffmpeg}, please make sure the installation is complete and FFmpeg path is set properly in preference.");
|
||||||
|
} else if(OS == os_macosx) {
|
||||||
|
var check_convert = ExecutedProcessReadFromStandardOutput(shell_execute("convert", ""));
|
||||||
|
if(string_pos(check_convert, "not found")) noti_warning($"No ImageMagick installed, please install imagemagick with homebrew or use the provided 'mac-libraries-installer.command'.");
|
||||||
|
|
||||||
|
var check_webp = ExecutedProcessReadFromStandardOutput(shell_execute("webp", ""));
|
||||||
|
if(string_pos(check_webp, "not found")) noti_warning($"No webp installed, please install webp with homwbrew or use the provided 'mac-libraries-installer.command'.");
|
||||||
|
|
||||||
|
var check_ffmpeg = ExecutedProcessReadFromStandardOutput(shell_execute("ffmpeg", ""));
|
||||||
|
if(string_pos(check_ffmpeg, "not found")) noti_warning($"No FFmpeg installed, please install FFmpeg with homebrew or use the provided 'mac-libraries-installer.command'.");
|
||||||
|
|
||||||
|
var _opt = "/opt/homebrew/bin/";
|
||||||
|
converter = _opt + "convert";
|
||||||
|
magick = _opt + "magick";
|
||||||
|
webp = _opt + "webp";
|
||||||
|
ffmpeg = _opt + "ffmpeg";
|
||||||
|
}
|
||||||
|
|
||||||
|
static onValueUpdate = function(_index) { #region
|
||||||
|
var form = getInputData(3);
|
||||||
|
|
||||||
|
if(_index == 3) {
|
||||||
|
if(NOT_LOAD) inputs[| 9].setValue(0);
|
||||||
|
|
||||||
|
switch(form) {
|
||||||
|
case 0 :
|
||||||
|
case 1 :
|
||||||
|
inputs[| 1].display_data = _format_still;
|
||||||
|
break;
|
||||||
|
case 2 :
|
||||||
|
inputs[| 1].display_data = _format_anim;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(NOT_LOAD && _index == 3 && form == 1)
|
||||||
|
inputs[| 2].setValue("%d%n%3f%i");
|
||||||
|
|
||||||
|
if(NOT_LOAD && _index == 1) {
|
||||||
|
var _path = getInputData(1);
|
||||||
|
var _ext = filename_ext(_path);
|
||||||
|
|
||||||
|
switch(_ext) {
|
||||||
|
case ".png" : inputs[| 9].setValue(0); break;
|
||||||
|
case ".jpg" : inputs[| 9].setValue(1); break;
|
||||||
|
|
||||||
|
case ".gif" : inputs[| 9].setValue(0); break;
|
||||||
|
case ".webp" : inputs[| 9].setValue(1); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static extensionCheck = function() { #region
|
||||||
|
var _path = getInputData(1);
|
||||||
|
var _ext = filename_ext(_path);
|
||||||
|
|
||||||
|
switch(_ext) {
|
||||||
|
case ".png" :
|
||||||
|
inputs[| 3].setValue(0);
|
||||||
|
inputs[| 9].setValue(0);
|
||||||
|
break;
|
||||||
|
case ".jpg" :
|
||||||
|
inputs[| 3].setValue(0);
|
||||||
|
inputs[| 9].setValue(1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ".gif" :
|
||||||
|
inputs[| 3].setValue(2);
|
||||||
|
inputs[| 9].setValue(0);
|
||||||
|
break;
|
||||||
|
case ".webp" :
|
||||||
|
inputs[| 3].setValue(2);
|
||||||
|
inputs[| 9].setValue(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static renderWebp = function(temp_path, target_path) { #region
|
||||||
|
var _path = file_find_first(temp_path + "*.png", 0);
|
||||||
|
var frames = [];
|
||||||
|
|
||||||
|
while(_path != "") {
|
||||||
|
var _frame = string_quote(temp_path + string_replace_all(_path, ".png", "") + ".webp");
|
||||||
|
var _pathTemp = string_quote(temp_path + _path);
|
||||||
|
var shell_cmd = _pathTemp + " -define webp:lossless=true " + _frame;
|
||||||
|
|
||||||
|
array_push(frames, _frame);
|
||||||
|
shell_execute_async(magick, shell_cmd, self, false);
|
||||||
|
|
||||||
|
_path = file_find_next();
|
||||||
|
}
|
||||||
|
|
||||||
|
var rate = getInputData(8);
|
||||||
|
if(rate == 0) rate = 1;
|
||||||
|
|
||||||
|
var framerate = round(1 / rate * 1000);
|
||||||
|
var cmd = "";
|
||||||
|
|
||||||
|
for( var i = 0, n = array_length(frames); i < n; i++ )
|
||||||
|
cmd += $"-frame {frames[i]} +{framerate}+0+0+1 ";
|
||||||
|
|
||||||
|
cmd += "-bgcolor 0,0,0,0 ";
|
||||||
|
cmd += "-o " + string_quote(target_path);
|
||||||
|
|
||||||
|
render_process_id = shell_execute_async(webp, cmd, self);
|
||||||
|
render_type = "webp";
|
||||||
|
render_target = target_path;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static renderGif = function(temp_path, target_path) { #region
|
||||||
|
var loop = getInputData( 5);
|
||||||
|
var opti = getInputData( 6);
|
||||||
|
var fuzz = getInputData( 7);
|
||||||
|
var rate = getInputData( 8);
|
||||||
|
var qual = getInputData(10);
|
||||||
|
if(rate == 0) rate = 1;
|
||||||
|
|
||||||
|
temp_path = string_replace_all(temp_path, "/", "\\");
|
||||||
|
target_path = string_replace_all(target_path, "/", "\\");
|
||||||
|
|
||||||
|
var framerate = 100 / rate;
|
||||||
|
var loop_str = loop? 0 : 1;
|
||||||
|
var use_gifski = false;
|
||||||
|
|
||||||
|
var shell_cmd = $"-delay {framerate} -alpha set -dispose 2 -loop {loop_str}";
|
||||||
|
if(opti) shell_cmd += $" -fuzz {fuzz * 100}% -layers OptimizeFrame -layers OptimizeTransparency";
|
||||||
|
shell_cmd += $" {string_quote(temp_path)} {string_quote(target_path)}";
|
||||||
|
|
||||||
|
render_process_id = shell_execute_async(converter, shell_cmd, self);
|
||||||
|
render_type = "gif";
|
||||||
|
render_target = target_path;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static renderMp4 = function(temp_path, target_path) { #region
|
||||||
|
var rate = getInputData( 8);
|
||||||
|
var qual = getInputData(10); qual = clamp(qual, 0, 51);
|
||||||
|
if(rate == 0) rate = 1;
|
||||||
|
|
||||||
|
if(file_exists_empty(target_path)) file_delete(target_path);
|
||||||
|
|
||||||
|
temp_path = string_replace_all(temp_path, "/", "\\");
|
||||||
|
target_path = string_replace_all(target_path, "/", "\\");
|
||||||
|
|
||||||
|
var shell_cmd = $"-hide_banner -loglevel quiet -framerate {rate} -i \"{temp_path}%05d.png\" -c:v libx264 -r {rate} -pix_fmt yuv420p -crf {qual} {string_quote(target_path)}";
|
||||||
|
|
||||||
|
render_process_id = shell_execute_async(ffmpeg, shell_cmd, self);
|
||||||
|
render_type = "mp4";
|
||||||
|
render_target = target_path;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static renderApng = function(temp_path, target_path) { #region
|
||||||
|
var rate = getInputData( 8);
|
||||||
|
if(rate == 0) rate = 1;
|
||||||
|
|
||||||
|
if(file_exists_empty(target_path)) file_delete(target_path);
|
||||||
|
|
||||||
|
temp_path = string_replace_all(temp_path, "/", "\\");
|
||||||
|
target_path = string_replace_all(target_path, "/", "\\");
|
||||||
|
|
||||||
|
var shell_cmd = $"-hide_banner -loglevel quiet -framerate {rate} -i \"{temp_path}%05d.png\" -plays 0 {string_quote(target_path)}";
|
||||||
|
|
||||||
|
render_process_id = shell_execute_async(ffmpeg, shell_cmd, self);
|
||||||
|
render_type = "apng";
|
||||||
|
render_target = target_path;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static pathString = function(path, index = 0, _array = false) { #region
|
||||||
|
var suff = getInputData( 2);
|
||||||
|
var form = getInputData( 3);
|
||||||
|
var strt = getInputData(11);
|
||||||
|
|
||||||
|
path = string_replace_all(path, "\\", "/");
|
||||||
|
|
||||||
|
var s = _array? [] : "";
|
||||||
|
var i = 1;
|
||||||
|
var ch, ch_s;
|
||||||
|
var len = string_length(suff);
|
||||||
|
|
||||||
|
while(i <= len) {
|
||||||
|
ch = string_char_at(suff, i);
|
||||||
|
|
||||||
|
if(ch == "%") {
|
||||||
|
i++;
|
||||||
|
var res = false, str = "";
|
||||||
|
|
||||||
|
do {
|
||||||
|
ch_s = string_char_at(suff, i);
|
||||||
|
switch(ch_s) {
|
||||||
|
case "f" :
|
||||||
|
var _txt = "";
|
||||||
|
var float_str = string_digits(str);
|
||||||
|
if(float_str != "") {
|
||||||
|
var float_val = string_digits(float_str);
|
||||||
|
var str_val = max(float_val - string_length(string(CURRENT_FRAME + 1 + strt)), 0);
|
||||||
|
repeat(str_val)
|
||||||
|
_txt += "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
_txt += string(CURRENT_FRAME + 1 + strt);
|
||||||
|
if(_array) array_push(s, [ "f", _txt ]);
|
||||||
|
else s += _txt;
|
||||||
|
res = true;
|
||||||
|
break;
|
||||||
|
case "i" :
|
||||||
|
var _txt = "";
|
||||||
|
var float_str = string_digits(str);
|
||||||
|
if(float_str != "") {
|
||||||
|
var float_val = string_digits(float_str);
|
||||||
|
var str_val = max(float_val - string_length(string(index)), 0);
|
||||||
|
repeat(str_val)
|
||||||
|
_txt += "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
_txt += string(index);
|
||||||
|
if(_array) array_push(s, [ "i", _txt ]);
|
||||||
|
else s += _txt;
|
||||||
|
res = true;
|
||||||
|
break;
|
||||||
|
case "d" :
|
||||||
|
var dir = filename_dir(path) + "/";
|
||||||
|
var _txt = "";
|
||||||
|
|
||||||
|
var float_str = string_digits(str);
|
||||||
|
if(float_str != "") {
|
||||||
|
var float_val = toNumber(string_digits(float_str)) + 1;
|
||||||
|
var dir_s = "";
|
||||||
|
var sep = string_splice(dir, "/");
|
||||||
|
|
||||||
|
for(var j = 0; j < array_length(sep) - float_val; j++)
|
||||||
|
dir_s += sep[j] + "/";
|
||||||
|
_txt += dir_s;
|
||||||
|
} else
|
||||||
|
_txt += dir;
|
||||||
|
|
||||||
|
if(_array) array_push(s, [ "d", _txt ]);
|
||||||
|
else s += _txt;
|
||||||
|
res = true;
|
||||||
|
break;
|
||||||
|
case "n" :
|
||||||
|
var ext = filename_ext(path);
|
||||||
|
var _txt = string_replace(filename_name(path), ext, "");
|
||||||
|
|
||||||
|
if(_array) array_push(s, [ "n", _txt ]);
|
||||||
|
else s += _txt;
|
||||||
|
res = true;
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
str += ch_s;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
} until(i > string_length(suff) || res);
|
||||||
|
} else {
|
||||||
|
if(_array) array_push(s, ch);
|
||||||
|
else s += ch;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _e = getInputData(9);
|
||||||
|
var _ext = array_safe_get_fast(inputs[| 9].display_data.data, _e, ".png");
|
||||||
|
|
||||||
|
if(_array) array_push(s, ["ext", _ext]);
|
||||||
|
else s += _ext;
|
||||||
|
|
||||||
|
return s;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static save_surface = function(_surf, _path) { #region
|
||||||
|
var form = getInputData(3);
|
||||||
|
//print($">>>>>>>>>>>>>>>>>>>> save surface {_surf} - {_path} <<<<<<<<<<<<<<<<<<<<");
|
||||||
|
|
||||||
|
if(form == NODE_EXPORT_FORMAT.animation) {
|
||||||
|
surface_save_safe(_surf, _path);
|
||||||
|
return _path;
|
||||||
|
}
|
||||||
|
|
||||||
|
var extd = getInputData( 9);
|
||||||
|
var qual = getInputData(10);
|
||||||
|
var indx = getInputData(13);
|
||||||
|
var ext = array_safe_get_fast(format_image, extd, ".png");
|
||||||
|
|
||||||
|
var _pathOut = _path;
|
||||||
|
var _pathTemp = $"{directory}/{irandom_range(10000, 99999)}.png";
|
||||||
|
|
||||||
|
switch(ext) {
|
||||||
|
case ".png":
|
||||||
|
switch(indx) {
|
||||||
|
case 0 :
|
||||||
|
surface_save_safe(_surf, _pathTemp);
|
||||||
|
|
||||||
|
var shell_cmd = $"convert {string_quote(_pathTemp)} {string_quote(_pathOut)}";
|
||||||
|
shell_execute_async(magick, shell_cmd, self);
|
||||||
|
break;
|
||||||
|
case 1 :
|
||||||
|
surface_save_safe(_surf, _pathTemp);
|
||||||
|
|
||||||
|
var shell_cmd = $"convert {string_quote(_pathTemp)} PNG8:{string_quote(_pathOut)}";
|
||||||
|
shell_execute_async(magick, shell_cmd, self);
|
||||||
|
break;
|
||||||
|
case 2 :
|
||||||
|
surface_save_safe(_surf, _pathOut);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ".jpg":
|
||||||
|
surface_save_safe(_surf, _pathTemp);
|
||||||
|
|
||||||
|
_pathOut = $"\"{string_replace_all(_path, ".png", "")}.jpg\"";
|
||||||
|
var shell_cmd = $"{string_quote(_pathTemp)} -quality {qual} {string_quote(_pathOut)}";
|
||||||
|
|
||||||
|
shell_execute_async(magick, shell_cmd, self);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ".webp":
|
||||||
|
surface_save_safe(_surf, _pathTemp);
|
||||||
|
|
||||||
|
_pathOut = $"\"{string_replace_all(_path, ".png", "")}.webp\"";
|
||||||
|
var shell_cmd = $"{string_quote(_pathTemp)} -quality {qual} -define webp:lossless=true {string_quote(_pathOut)}";
|
||||||
|
|
||||||
|
shell_execute_async(magick, shell_cmd, self);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _pathOut;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static export = function() { #region
|
||||||
|
//print($">>>>>>>>>>>>>>>>>>>> export {CURRENT_FRAME} <<<<<<<<<<<<<<<<<<<<");
|
||||||
|
|
||||||
|
var surf = getInputData( 0);
|
||||||
|
var path = getInputData( 1);
|
||||||
|
var suff = getInputData( 2);
|
||||||
|
var form = getInputData( 3);
|
||||||
|
var rang = getInputData(12);
|
||||||
|
var stps = getInputData(14);
|
||||||
|
var user = getInputData(15);
|
||||||
|
|
||||||
|
if(form >= 1 && user) {
|
||||||
|
var rng_s = rang[0];
|
||||||
|
var rng_e = rang[1];
|
||||||
|
var rng_st = stps >= 1? (CURRENT_FRAME - rng_s) % stps : 0;
|
||||||
|
|
||||||
|
if(CURRENT_FRAME < rng_s - 1) return;
|
||||||
|
if(CURRENT_FRAME > rng_e - 1) return;
|
||||||
|
if(rng_st != 0) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_array(surf)) {
|
||||||
|
var p = "";
|
||||||
|
for(var i = 0; i < array_length(surf); i++) {
|
||||||
|
var _surf = surf[i];
|
||||||
|
if(!is_surface(_surf)) continue;
|
||||||
|
|
||||||
|
if(form == NODE_EXPORT_FORMAT.animation) {
|
||||||
|
p = $"{directory}/{i}/{string_lead_zero(CURRENT_FRAME, 5)}.png";
|
||||||
|
} else {
|
||||||
|
if(is_array(path) && array_length(path) == array_length(surf))
|
||||||
|
p = pathString(array_safe_get_fast(path, i), i);
|
||||||
|
else
|
||||||
|
p = pathString(path, i);
|
||||||
|
CLI_EXPORT_AMOUNT++;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = save_surface(_surf, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(form != NODE_EXPORT_FORMAT.animation && !IS_CMD) {
|
||||||
|
var noti = log_message("EXPORT", $"Export {array_length(surf)} images complete.", THEME.noti_icon_tick, COLORS._main_value_positive, false);
|
||||||
|
noti.path = filename_dir(p);
|
||||||
|
noti.setOnClick(function() { shellOpenExplorer(self.path); }, "Open in explorer", THEME.explorer);
|
||||||
|
|
||||||
|
PANEL_MENU.setNotiIcon(THEME.noti_icon_tick);
|
||||||
|
}
|
||||||
|
} else if(is_surface(surf)) {
|
||||||
|
var p = path;
|
||||||
|
if(is_array(path)) p = path[0];
|
||||||
|
|
||||||
|
if(form == NODE_EXPORT_FORMAT.animation) {
|
||||||
|
p = $"{directory}/{string_lead_zero(CURRENT_FRAME, 5)}.png";
|
||||||
|
} else {
|
||||||
|
p = pathString(p);
|
||||||
|
CLI_EXPORT_AMOUNT++;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = save_surface(surf, p);
|
||||||
|
|
||||||
|
if(form != NODE_EXPORT_FORMAT.animation && !IS_CMD) {
|
||||||
|
var noti = log_message("EXPORT", $"Export image as {p}", THEME.noti_icon_tick, COLORS._main_value_positive, false);
|
||||||
|
noti.path = filename_dir(p);
|
||||||
|
noti.setOnClick(function() { shellOpenExplorer(self.path); }, "Open in explorer", THEME.explorer);
|
||||||
|
|
||||||
|
PANEL_MENU.setNotiIcon(THEME.noti_icon_tick);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static renderCompleted = function() { #region
|
||||||
|
var surf = getInputData( 0);
|
||||||
|
var path = getInputData( 1);
|
||||||
|
var suff = getInputData( 2);
|
||||||
|
var extd = getInputData( 9);
|
||||||
|
var temp_path, target_path;
|
||||||
|
|
||||||
|
update_on_frame = false;
|
||||||
|
|
||||||
|
if(is_array(surf)) {
|
||||||
|
for(var i = 0; i < array_length(surf); i++) {
|
||||||
|
temp_path = $"{directory}/{i}/*.png";
|
||||||
|
if(is_array(path)) target_path = pathString(array_safe_get_fast(path, i), i);
|
||||||
|
else target_path = pathString(path, i);
|
||||||
|
|
||||||
|
switch(format_animation[extd]) {
|
||||||
|
case ".gif" :
|
||||||
|
target_path = string_replace(target_path, ".png", ".gif");
|
||||||
|
renderGif(temp_path, target_path);
|
||||||
|
break;
|
||||||
|
case ".webp" :
|
||||||
|
target_path = string_replace(target_path, ".png", ".webp");
|
||||||
|
renderWebp(temp_path, target_path);
|
||||||
|
break;
|
||||||
|
case ".mp4" :
|
||||||
|
target_path = string_replace(target_path, ".png", ".mp4");
|
||||||
|
renderMp4(temp_path, target_path);
|
||||||
|
break;
|
||||||
|
case ".apng" :
|
||||||
|
target_path = string_replace(target_path, ".png", ".apng");
|
||||||
|
renderApng(temp_path, target_path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
target_path = pathString(path);
|
||||||
|
|
||||||
|
switch(format_animation[extd]) {
|
||||||
|
case ".gif" :
|
||||||
|
target_path = string_replace(target_path, ".png", ".gif");
|
||||||
|
renderGif(directory + "/*.png", target_path);
|
||||||
|
break;
|
||||||
|
case ".webp" :
|
||||||
|
target_path = string_replace(target_path, ".png", ".webp");
|
||||||
|
renderWebp(directory + "/", target_path);
|
||||||
|
break;
|
||||||
|
case ".mp4" :
|
||||||
|
target_path = string_replace(target_path, ".png", ".mp4");
|
||||||
|
renderMp4(directory + "/", target_path);
|
||||||
|
break;
|
||||||
|
case ".apng" :
|
||||||
|
target_path = string_replace(target_path, ".png", ".apng");
|
||||||
|
renderApng(directory + "/", target_path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedOutTrigger.setValue(true);
|
||||||
|
CLI_EXPORT_AMOUNT++;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
insp1UpdateTooltip = "Export";
|
||||||
|
insp1UpdateIcon = [ THEME.sequence_control, 1, COLORS._main_value_positive ];
|
||||||
|
|
||||||
|
insp2UpdateTooltip = "Export All";
|
||||||
|
insp2UpdateIcon = [ THEME.play_all, 0, COLORS._main_value_positive ];
|
||||||
|
|
||||||
|
static onInspector1Update = function() { #region
|
||||||
|
if(IS_RENDERING) return;
|
||||||
|
|
||||||
|
if(isInLoop()) RENDER_ALL
|
||||||
|
else doInspectorAction();
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static onInspector2Update = function() { #region
|
||||||
|
if(IS_RENDERING) return;
|
||||||
|
exportAll();
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static doInspectorAction = function() { #region
|
||||||
|
if(!IS_CMD && (LOADING || APPENDING)) return;
|
||||||
|
|
||||||
|
var path = getInputData(1);
|
||||||
|
if(path == "") return;
|
||||||
|
var form = getInputData(3);
|
||||||
|
|
||||||
|
if(form == NODE_EXPORT_FORMAT.single) {
|
||||||
|
Render();
|
||||||
|
|
||||||
|
export();
|
||||||
|
updatedOutTrigger.setValue(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
update_on_frame = true;
|
||||||
|
playing = true;
|
||||||
|
played = 0;
|
||||||
|
|
||||||
|
PROJECT.animator.render();
|
||||||
|
|
||||||
|
if(IS_CMD) array_push(PROGRAM_ARGUMENTS._exporting, node_id);
|
||||||
|
|
||||||
|
if(directory_exists(directory))
|
||||||
|
directory_destroy(directory);
|
||||||
|
directory_create(directory);
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static step = function() { #region
|
||||||
|
insp1UpdateActive = !IS_RENDERING;
|
||||||
|
insp2UpdateActive = !IS_RENDERING;
|
||||||
|
|
||||||
|
var surf = getInputData( 0);
|
||||||
|
var pngf = getInputData(13);
|
||||||
|
|
||||||
|
if(is_array(surf)) {
|
||||||
|
inputs[| 3].display_data.data = format_array;
|
||||||
|
inputs[| 3].editWidget.data_list = format_array;
|
||||||
|
} else {
|
||||||
|
inputs[| 3].display_data.data = format_single;
|
||||||
|
inputs[| 3].editWidget.data_list = format_single;
|
||||||
|
}
|
||||||
|
|
||||||
|
outputs[| 1].setValue(surf);
|
||||||
|
|
||||||
|
var anim = getInputData(3); // single, sequence, animation
|
||||||
|
var extn = getInputData(9);
|
||||||
|
var user = getInputData(15);
|
||||||
|
|
||||||
|
inputs[| 11].setVisible(anim == 1);
|
||||||
|
|
||||||
|
inputs[| 12].editWidget.minn = FIRST_FRAME + 1;
|
||||||
|
inputs[| 12].editWidget.maxx = LAST_FRAME + 1;
|
||||||
|
if(!user) inputs[| 12].setValueDirect([ FIRST_FRAME + 1, LAST_FRAME + 1], noone, false, 0, false);
|
||||||
|
|
||||||
|
inputs[| 14].setVisible(anim > 0);
|
||||||
|
|
||||||
|
if(anim == NODE_EXPORT_FORMAT.animation) {
|
||||||
|
var _fmt = array_safe_get_fast(format_animation, extn);
|
||||||
|
|
||||||
|
inputs[| 5].setVisible(_fmt == ".gif");
|
||||||
|
inputs[| 6].setVisible(_fmt == ".gif");
|
||||||
|
inputs[| 7].setVisible(_fmt == ".gif");
|
||||||
|
inputs[| 8].setVisible(true);
|
||||||
|
|
||||||
|
inputs[| 9].display_data.data = format_animation;
|
||||||
|
inputs[| 9].editWidget.data_list = format_animation;
|
||||||
|
|
||||||
|
inputs[| 13].setVisible(false);
|
||||||
|
|
||||||
|
if(_fmt == ".mp4") {
|
||||||
|
inputs[| 10].setName("CRF value");
|
||||||
|
inputs[| 10].tooltip = "Quality of the output, with 0 being the highest (and largest file size), and 51 being the lowest.";
|
||||||
|
|
||||||
|
inputs[| 10].setVisible(true);
|
||||||
|
inputs[| 10].editWidget.minn = 0;
|
||||||
|
inputs[| 10].editWidget.maxx = 51;
|
||||||
|
} else
|
||||||
|
inputs[| 10].setVisible(false);
|
||||||
|
} else {
|
||||||
|
var _fmt = array_safe_get_fast(format_image, extn);
|
||||||
|
|
||||||
|
inputs[| 5].setVisible(false);
|
||||||
|
inputs[| 6].setVisible(false);
|
||||||
|
inputs[| 7].setVisible(false);
|
||||||
|
inputs[| 8].setVisible(false);
|
||||||
|
|
||||||
|
inputs[| 9].display_data.data = format_image;
|
||||||
|
inputs[| 9].editWidget.data_list = format_image;
|
||||||
|
|
||||||
|
inputs[| 13].setVisible(_fmt == ".png");
|
||||||
|
|
||||||
|
if(_fmt == ".jpg" || _fmt == ".webp") {
|
||||||
|
inputs[| 10].setName("Quality");
|
||||||
|
inputs[| 10].tooltip = "Quality of the output.";
|
||||||
|
|
||||||
|
inputs[| 10].setVisible(true);
|
||||||
|
inputs[| 10].editWidget.minn = 0;
|
||||||
|
inputs[| 10].editWidget.maxx = 100;
|
||||||
|
} else
|
||||||
|
inputs[| 10].setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
outputs[| 0].visible = isInLoop();
|
||||||
|
|
||||||
|
if(render_process_id != 0) {
|
||||||
|
var res = ProcIdExists(render_process_id);
|
||||||
|
|
||||||
|
if(res == 0 || OS == os_macosx) {
|
||||||
|
if(!IS_CMD) {
|
||||||
|
var noti = log_message("EXPORT", $"Export {render_type} as {render_target}", THEME.noti_icon_tick, COLORS._main_value_positive, false);
|
||||||
|
noti.path = filename_dir(render_target);
|
||||||
|
noti.setOnClick(function() { shellOpenExplorer(self.path); }, "Open in explorer", THEME.explorer);
|
||||||
|
PANEL_MENU.setNotiIcon(THEME.noti_icon_tick);
|
||||||
|
}
|
||||||
|
|
||||||
|
render_process_id = 0;
|
||||||
|
|
||||||
|
if(IS_CMD) array_remove(PROGRAM_ARGUMENTS._exporting, node_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static update = function(frame = CURRENT_FRAME) { #region
|
||||||
|
var anim = getInputData(3);
|
||||||
|
if(anim == NODE_EXPORT_FORMAT.single) {
|
||||||
|
if(isInLoop()) export();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!PROJECT.animator.is_playing) {
|
||||||
|
playing = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!playing) return;
|
||||||
|
|
||||||
|
export();
|
||||||
|
|
||||||
|
if(IS_LAST_FRAME && anim == NODE_EXPORT_FORMAT.animation)
|
||||||
|
renderCompleted();
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) { #region
|
||||||
|
graph_preview_alpha = 1;
|
||||||
|
if(render_process_id != 0) {
|
||||||
|
graph_preview_alpha = 0.5;
|
||||||
|
draw_sprite_ui(THEME.loading, 0, xx + w * _s / 2, yy + h * _s / 2, _s, _s, current_time / 2, COLORS._main_icon, 1);
|
||||||
|
}
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static doApplyDeserialize = function() { onValueUpdate(3); }
|
||||||
|
}
|
129
#backups/scripts/node_random_tile/node_random_tile.gml.backup0
Normal file
129
#backups/scripts/node_random_tile/node_random_tile.gml.backup0
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
// 2024-05-01 09:30:41
|
||||||
|
function Node_Random_Tile(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
|
||||||
|
name = "Random Tile";
|
||||||
|
|
||||||
|
inputs[| 0] = nodeValue("Dimension", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, DEF_SURF )
|
||||||
|
.setDisplay(VALUE_DISPLAY.vector);
|
||||||
|
|
||||||
|
inputs[| 1] = nodeValue("Position", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ])
|
||||||
|
.setDisplay(VALUE_DISPLAY.vector)
|
||||||
|
.setUnitRef(function(index) { return getDimension(index); });
|
||||||
|
|
||||||
|
inputs[| 2] = nodeValue("Scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 2, 2 ])
|
||||||
|
.setDisplay(VALUE_DISPLAY.vector)
|
||||||
|
.setMappable(11);
|
||||||
|
|
||||||
|
inputs[| 3] = nodeValue("Angle", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0)
|
||||||
|
.setDisplay(VALUE_DISPLAY.rotation)
|
||||||
|
.setMappable(12);
|
||||||
|
|
||||||
|
inputs[| 4] = nodeValue("Gap", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1)
|
||||||
|
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 0.5, 0.001] })
|
||||||
|
.setMappable(13);
|
||||||
|
|
||||||
|
inputs[| 5] = nodeValue("Tile color", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white) )
|
||||||
|
.setMappable(17);
|
||||||
|
|
||||||
|
inputs[| 6] = nodeValue("Gap color", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, c_black);
|
||||||
|
|
||||||
|
inputs[| 7] = nodeValue("Render type", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
|
||||||
|
.setDisplay(VALUE_DISPLAY.enum_scroll, ["Colored tile", "Height map", "Texture grid"]);
|
||||||
|
|
||||||
|
inputs[| 8] = nodeValue("Seed", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, irandom_range(10000, 99999));
|
||||||
|
|
||||||
|
inputs[| 9] = nodeValue("Texture", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone);
|
||||||
|
|
||||||
|
inputs[| 10] = nodeValue("Anti aliasing", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inputs[| 11] = nodeValueMap("Scale map", self);
|
||||||
|
|
||||||
|
inputs[| 12] = nodeValueMap("Angle map", self);
|
||||||
|
|
||||||
|
inputs[| 13] = nodeValueMap("Gap map", self);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inputs[| 14] = nodeValue("Truchet", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
|
||||||
|
|
||||||
|
inputs[| 15] = nodeValue("Truchet seed", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, seed_random());
|
||||||
|
|
||||||
|
inputs[| 16] = nodeValue("Truchet threshold", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.5)
|
||||||
|
.setDisplay(VALUE_DISPLAY.slider)
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inputs[| 17] = nodeValueMap("Gradient map", self);
|
||||||
|
|
||||||
|
inputs[| 18] = nodeValueGradientRange("Gradient map range", self, inputs[| 5]);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inputs[| 19] = nodeValue("Texture angle", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ])
|
||||||
|
.setDisplay(VALUE_DISPLAY.rotation_range);
|
||||||
|
|
||||||
|
input_display_list = [
|
||||||
|
["Output", false], 0,
|
||||||
|
["Pattern", false], 1, 3, 12, 2, 11, 4, 13,
|
||||||
|
["Render", false], 7, 8, 5, 17, 6, 9, 10,
|
||||||
|
["Truchet", true, 14], 15, 16, 19,
|
||||||
|
];
|
||||||
|
|
||||||
|
outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
|
||||||
|
|
||||||
|
attribute_surface_depth();
|
||||||
|
|
||||||
|
static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
|
||||||
|
var a = inputs[| 1].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); active &= !a;
|
||||||
|
var a = inputs[| 18].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny, getSingleValue(0)); active &= !a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static step = function() { #region
|
||||||
|
inputs[| 2].mappableStep();
|
||||||
|
inputs[| 3].mappableStep();
|
||||||
|
inputs[| 4].mappableStep();
|
||||||
|
inputs[| 5].mappableStep();
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static processData = function(_outSurf, _data, _output_index, _array_index) {
|
||||||
|
var _dim = _data[0];
|
||||||
|
var _pos = _data[1];
|
||||||
|
var _sam = _data[9];
|
||||||
|
var _mode = _data[7];
|
||||||
|
|
||||||
|
var _col_gap = _data[6];
|
||||||
|
|
||||||
|
inputs[| 5].setVisible(_mode == 0);
|
||||||
|
inputs[| 6].setVisible(_mode != 1);
|
||||||
|
inputs[| 9].setVisible(_mode == 2 || _mode == 3);
|
||||||
|
|
||||||
|
_outSurf = surface_verify(_outSurf, _dim[0], _dim[1], attrDepth());
|
||||||
|
|
||||||
|
surface_set_shader(_outSurf, sh_random_tile);
|
||||||
|
shader_set_f("dimension", _dim[0], _dim[1]);
|
||||||
|
shader_set_f("position", _pos[0] / _dim[0], _pos[1] / _dim[1]);
|
||||||
|
|
||||||
|
shader_set_f_map("scale", _data[ 2], _data[11], inputs[| 2]);
|
||||||
|
shader_set_f_map("angle", _data[ 3], _data[12], inputs[| 3]);
|
||||||
|
shader_set_f_map("thick", _data[ 4], _data[13], inputs[| 4]);
|
||||||
|
|
||||||
|
shader_set_f("seed", _data[ 8]);
|
||||||
|
shader_set_i("mode", _mode);
|
||||||
|
shader_set_i("aa", _data[10]);
|
||||||
|
shader_set_color("gapCol", _col_gap);
|
||||||
|
|
||||||
|
shader_set_i("textureTruchet", _data[14]);
|
||||||
|
shader_set_f("truchetSeed", _data[15]);
|
||||||
|
shader_set_f("truchetThres", _data[16]);
|
||||||
|
shader_set_f("truchetAngle", _data[19]);
|
||||||
|
|
||||||
|
shader_set_gradient(_data[5], _data[17], _data[18], inputs[| 5]);
|
||||||
|
|
||||||
|
if(is_surface(_sam)) draw_surface_stretched_safe(_sam, 0, 0, _dim[0], _dim[1]);
|
||||||
|
else draw_sprite_ext(s_fx_pixel, 0, 0, 0, _dim[0], _dim[1], 0, c_white, 1);
|
||||||
|
surface_reset_shader();
|
||||||
|
|
||||||
|
return _outSurf;
|
||||||
|
}
|
||||||
|
}
|
129
#backups/scripts/node_random_tile/node_random_tile.gml.backup1
Normal file
129
#backups/scripts/node_random_tile/node_random_tile.gml.backup1
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
// 2024-05-01 09:29:37
|
||||||
|
function Node_Random_Tile(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
|
||||||
|
name = "Random Tile";
|
||||||
|
|
||||||
|
inputs[| 0] = nodeValue("Dimension", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, DEF_SURF )
|
||||||
|
.setDisplay(VALUE_DISPLAY.vector);
|
||||||
|
|
||||||
|
inputs[| 1] = nodeValue("Position", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ])
|
||||||
|
.setDisplay(VALUE_DISPLAY.vector)
|
||||||
|
.setUnitRef(function(index) { return getDimension(index); });
|
||||||
|
|
||||||
|
inputs[| 2] = nodeValue("Scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 2, 2 ])
|
||||||
|
.setDisplay(VALUE_DISPLAY.vector)
|
||||||
|
.setMappable(11);
|
||||||
|
|
||||||
|
inputs[| 3] = nodeValue("Angle", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0)
|
||||||
|
.setDisplay(VALUE_DISPLAY.rotation)
|
||||||
|
.setMappable(12);
|
||||||
|
|
||||||
|
inputs[| 4] = nodeValue("Gap", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1)
|
||||||
|
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 0.5, 0.001] })
|
||||||
|
.setMappable(13);
|
||||||
|
|
||||||
|
inputs[| 5] = nodeValue("Tile color", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white) )
|
||||||
|
.setMappable(17);
|
||||||
|
|
||||||
|
inputs[| 6] = nodeValue("Gap color", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, c_black);
|
||||||
|
|
||||||
|
inputs[| 7] = nodeValue("Render type", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
|
||||||
|
.setDisplay(VALUE_DISPLAY.enum_scroll, ["Colored tile", "Height map", "Texture grid"]);
|
||||||
|
|
||||||
|
inputs[| 8] = nodeValue("Seed", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, irandom_range(10000, 99999));
|
||||||
|
|
||||||
|
inputs[| 9] = nodeValue("Texture", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone);
|
||||||
|
|
||||||
|
inputs[| 10] = nodeValue("Anti aliasing", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inputs[| 11] = nodeValueMap("Scale map", self);
|
||||||
|
|
||||||
|
inputs[| 12] = nodeValueMap("Angle map", self);
|
||||||
|
|
||||||
|
inputs[| 13] = nodeValueMap("Gap map", self);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inputs[| 14] = nodeValue("Truchet", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
|
||||||
|
|
||||||
|
inputs[| 15] = nodeValue("Truchet seed", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, seed_random());
|
||||||
|
|
||||||
|
inputs[| 16] = nodeValue("Truchet threshold", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.5)
|
||||||
|
.setDisplay(VALUE_DISPLAY.slider)
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inputs[| 17] = nodeValueMap("Gradient map", self);
|
||||||
|
|
||||||
|
inputs[| 18] = nodeValueGradientRange("Gradient map range", self, inputs[| 5]);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inputs[| 19] = nodeValue("Texture angle", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ])
|
||||||
|
.setDisplay(VALUE_DISPLAY.rotation_range);
|
||||||
|
|
||||||
|
input_display_list = [
|
||||||
|
["Output", false], 0,
|
||||||
|
["Pattern", false], 1, 3, 12, 2, 11, 4, 13,
|
||||||
|
["Render", false], 7, 8, 5, 17, 6, 9, 10,
|
||||||
|
["Truchet", true, 14], 15, 16, 19,
|
||||||
|
];
|
||||||
|
|
||||||
|
outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
|
||||||
|
|
||||||
|
attribute_surface_depth();
|
||||||
|
|
||||||
|
static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
|
||||||
|
var a = inputs[| 1].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); active &= !a;
|
||||||
|
var a = inputs[| 18].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny, getSingleValue(0)); active &= !a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static step = function() { #region
|
||||||
|
inputs[| 2].mappableStep();
|
||||||
|
inputs[| 3].mappableStep();
|
||||||
|
inputs[| 4].mappableStep();
|
||||||
|
inputs[| 5].mappableStep();
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
static processData = function(_outSurf, _data, _output_index, _array_index) {
|
||||||
|
var _dim = _data[0];
|
||||||
|
var _pos = _data[1];
|
||||||
|
var _sam = _data[9];
|
||||||
|
var _mode = _data[7];
|
||||||
|
|
||||||
|
var _col_gap = _data[6];
|
||||||
|
|
||||||
|
inputs[| 5].setVisible(_mode == 0);
|
||||||
|
inputs[| 6].setVisible(_mode != 1);
|
||||||
|
inputs[| 9].setVisible(_mode == 2 || _mode == 3);
|
||||||
|
|
||||||
|
_outSurf = surface_verify(_outSurf, _dim[0], _dim[1], attrDepth());
|
||||||
|
|
||||||
|
surface_set_shader(_outSurf, sh_random_tile);
|
||||||
|
shader_set_f("dimension", _dim[0], _dim[1]);
|
||||||
|
shader_set_f("position", _pos[0] / _dim[0], _pos[1] / _dim[1]);
|
||||||
|
|
||||||
|
shader_set_f_map("scale", _data[ 2], _data[11], inputs[| 2]);
|
||||||
|
shader_set_f_map("angle", _data[ 3], _data[12], inputs[| 3]);
|
||||||
|
shader_set_f_map("thick", _data[ 4], _data[13], inputs[| 4]);
|
||||||
|
|
||||||
|
shader_set_f("seed", _data[ 8]);
|
||||||
|
shader_set_i("mode", _mode);
|
||||||
|
shader_set_i("aa", _data[10]);
|
||||||
|
shader_set_color("gapCol", _col_gap);
|
||||||
|
|
||||||
|
shader_set_i("textureTruchet", _data[14]);
|
||||||
|
shader_set_f("truchetSeed", _data[15]);
|
||||||
|
shader_set_f("truchetThres", _data[16]);
|
||||||
|
shader_set_f("truchetAngle", _data[19]);
|
||||||
|
|
||||||
|
shader_set_gradient(_data[5], _data[17], _data[18], inputs[| 5]);
|
||||||
|
|
||||||
|
if(is_surface(_sam)) draw_surface_stretched_safe(_sam, 0, 0, _dim[0], _dim[1]);
|
||||||
|
else draw_sprite_ext(s_fx_pixel, 0, 0, 0, _dim[0], _dim[1], 0, c_white, 1);
|
||||||
|
surface_reset_shader();
|
||||||
|
|
||||||
|
return _outSurf;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// 2024-04-28 11:37:34
|
// 2024-05-01 19:28:09
|
||||||
#region ---- global names ----
|
#region ---- global names ----
|
||||||
global.junctionEndName = [ "Hold", "Loop", "Ping pong", "Wrap" ];
|
global.junctionEndName = [ "Hold", "Loop", "Ping pong", "Wrap" ];
|
||||||
|
|
||||||
|
@ -1152,7 +1152,7 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
|
||||||
});
|
});
|
||||||
|
|
||||||
extract_node = "Node_Vector4";
|
extract_node = "Node_Vector4";
|
||||||
display_data.angle_display = QUARTERNION_DISPLAY.quarterion;
|
display_data.angle_display = QUARTERNION_DISPLAY.euler;
|
||||||
break; #endregion
|
break; #endregion
|
||||||
|
|
||||||
case VALUE_DISPLAY.path_anchor : #region
|
case VALUE_DISPLAY.path_anchor : #region
|
||||||
|
@ -1552,19 +1552,6 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
|
||||||
return applyUnit? unit.apply(value, arrIndex) : value;
|
return applyUnit? unit.apply(value, arrIndex) : value;
|
||||||
} #endregion
|
} #endregion
|
||||||
|
|
||||||
if(display_type == VALUE_DISPLAY.d3quarternion) { #region
|
|
||||||
if(!applyUnit) return value;
|
|
||||||
var dispType = display_data.angle_display;
|
|
||||||
|
|
||||||
switch(dispType) {
|
|
||||||
case QUARTERNION_DISPLAY.quarterion :
|
|
||||||
return value;
|
|
||||||
case QUARTERNION_DISPLAY.euler :
|
|
||||||
var euler = new BBMOD_Quaternion().FromEuler(value[0], value[1], value[2]).ToArray();
|
|
||||||
return euler;
|
|
||||||
}
|
|
||||||
} #endregion
|
|
||||||
|
|
||||||
if(type == VALUE_TYPE.text) { #region
|
if(type == VALUE_TYPE.text) { #region
|
||||||
switch(display_type) {
|
switch(display_type) {
|
||||||
case VALUE_DISPLAY.text_array : return value;
|
case VALUE_DISPLAY.text_array : return value;
|
||||||
|
@ -1911,6 +1898,13 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
|
||||||
} else
|
} else
|
||||||
val = ds_list_empty(animator.values)? 0 : animator.processType(animator.values[| 0].value);
|
val = ds_list_empty(animator.values)? 0 : animator.processType(animator.values[| 0].value);
|
||||||
|
|
||||||
|
if(display_type == VALUE_DISPLAY.d3quarternion) {
|
||||||
|
switch(display_data.angle_display) {
|
||||||
|
case QUARTERNION_DISPLAY.quarterion : return val;
|
||||||
|
case QUARTERNION_DISPLAY.euler : return new BBMOD_Quaternion(val[0], val[1], val[2], val[3]).ToEuler(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
} #endregion
|
} #endregion
|
||||||
|
|
||||||
|
@ -1993,6 +1987,7 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
|
||||||
|
|
||||||
static setValueInspector = function(val = 0, index = noone) { #region
|
static setValueInspector = function(val = 0, index = noone) { #region
|
||||||
INLINE
|
INLINE
|
||||||
|
|
||||||
var res = false;
|
var res = false;
|
||||||
val = unit.invApply(val);
|
val = unit.invApply(val);
|
||||||
|
|
||||||
|
@ -2003,27 +1998,32 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
|
||||||
var _node = PANEL_INSPECTOR.inspectings[i];
|
var _node = PANEL_INSPECTOR.inspectings[i];
|
||||||
if(ind >= ds_list_size(_node.inputs)) continue;
|
if(ind >= ds_list_size(_node.inputs)) continue;
|
||||||
|
|
||||||
var r = _node.inputs[| ind].setValueDirect(val, index);
|
var r = _node.inputs[| ind].setValueInspectorDirect(val, index);
|
||||||
if(_node == node) res = r;
|
if(_node == node) res = r;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
res = setValueDirect(val, index);
|
res = setValueInspectorDirect(val, index);
|
||||||
|
|
||||||
//print($"Node {node} : {node.name} {node.internalName}");
|
|
||||||
//print($"Inspecting {PANEL_INSPECTOR.inspecting} : {PANEL_INSPECTOR.inspecting.name} {PANEL_INSPECTOR.inspecting.internalName}");
|
|
||||||
//print($"{node == PANEL_INSPECTOR.inspecting}");
|
|
||||||
//print("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
} #endregion
|
} #endregion
|
||||||
|
|
||||||
|
static setValueInspectorDirect = function(val = 0, index = noone) {
|
||||||
|
if(display_type == VALUE_DISPLAY.d3quarternion && display_data.angle_display == QUARTERNION_DISPLAY.euler) {
|
||||||
|
var _qval = new BBMOD_Quaternion().FromEuler(-val[0], -val[1], -val[2]).ToArray();
|
||||||
|
var _eval = new BBMOD_Quaternion(_qval[0], _qval[1], _qval[2], _qval[3]).ToEuler(true);
|
||||||
|
return setValueDirect(_qval);
|
||||||
|
}
|
||||||
|
|
||||||
|
return setValueDirect(val, index);
|
||||||
|
}
|
||||||
|
|
||||||
static setValueDirect = function(val = 0, index = noone, record = true, time = CURRENT_FRAME, _update = true) { #region
|
static setValueDirect = function(val = 0, index = noone, record = true, time = CURRENT_FRAME, _update = true) { #region
|
||||||
is_modified = true;
|
is_modified = true;
|
||||||
var updated = false;
|
var updated = false;
|
||||||
var _val = val;
|
var _val = val;
|
||||||
var _inp = connect_type == JUNCTION_CONNECT.input;
|
var _inp = connect_type == JUNCTION_CONNECT.input;
|
||||||
|
|
||||||
if(sep_axis) {
|
if(sep_axis) {
|
||||||
if(index == noone) {
|
if(index == noone) {
|
||||||
for( var i = 0, n = array_length(animators); i < n; i++ )
|
for( var i = 0, n = array_length(animators); i < n; i++ )
|
||||||
|
@ -2039,8 +2039,7 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
|
||||||
_val[index] = val;
|
_val[index] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
updated = animator.setValue(_val, _inp && record, time);
|
updated = animator.setValue(_val, _inp && record, time);
|
||||||
//print($"{updated}: {index} - {_val}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type == VALUE_TYPE.gradient) updated = true;
|
if(type == VALUE_TYPE.gradient) updated = true;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// 2024-04-28 11:29:46
|
// 2024-05-01 19:27:29
|
||||||
#region ---- global names ----
|
#region ---- global names ----
|
||||||
global.junctionEndName = [ "Hold", "Loop", "Ping pong", "Wrap" ];
|
global.junctionEndName = [ "Hold", "Loop", "Ping pong", "Wrap" ];
|
||||||
|
|
||||||
|
@ -1152,7 +1152,7 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
|
||||||
});
|
});
|
||||||
|
|
||||||
extract_node = "Node_Vector4";
|
extract_node = "Node_Vector4";
|
||||||
display_data.angle_display = QUARTERNION_DISPLAY.quarterion;
|
display_data.angle_display = QUARTERNION_DISPLAY.euler;
|
||||||
break; #endregion
|
break; #endregion
|
||||||
|
|
||||||
case VALUE_DISPLAY.path_anchor : #region
|
case VALUE_DISPLAY.path_anchor : #region
|
||||||
|
@ -1552,19 +1552,6 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
|
||||||
return applyUnit? unit.apply(value, arrIndex) : value;
|
return applyUnit? unit.apply(value, arrIndex) : value;
|
||||||
} #endregion
|
} #endregion
|
||||||
|
|
||||||
if(display_type == VALUE_DISPLAY.d3quarternion) { #region
|
|
||||||
if(!applyUnit) return value;
|
|
||||||
var dispType = display_data.angle_display;
|
|
||||||
|
|
||||||
switch(dispType) {
|
|
||||||
case QUARTERNION_DISPLAY.quarterion :
|
|
||||||
return value;
|
|
||||||
case QUARTERNION_DISPLAY.euler :
|
|
||||||
var euler = new BBMOD_Quaternion().FromEuler(value[0], value[1], value[2]).ToArray();
|
|
||||||
return euler;
|
|
||||||
}
|
|
||||||
} #endregion
|
|
||||||
|
|
||||||
if(type == VALUE_TYPE.text) { #region
|
if(type == VALUE_TYPE.text) { #region
|
||||||
switch(display_type) {
|
switch(display_type) {
|
||||||
case VALUE_DISPLAY.text_array : return value;
|
case VALUE_DISPLAY.text_array : return value;
|
||||||
|
@ -1911,6 +1898,13 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
|
||||||
} else
|
} else
|
||||||
val = ds_list_empty(animator.values)? 0 : animator.processType(animator.values[| 0].value);
|
val = ds_list_empty(animator.values)? 0 : animator.processType(animator.values[| 0].value);
|
||||||
|
|
||||||
|
if(display_type == VALUE_DISPLAY.d3quarternion) {
|
||||||
|
switch(display_data.angle_display) {
|
||||||
|
case QUARTERNION_DISPLAY.quarterion : return val;
|
||||||
|
case QUARTERNION_DISPLAY.euler : return new BBMOD_Quaternion(val[0], val[1], val[2], val[3]).ToEuler(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
} #endregion
|
} #endregion
|
||||||
|
|
||||||
|
@ -1993,6 +1987,7 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
|
||||||
|
|
||||||
static setValueInspector = function(val = 0, index = noone) { #region
|
static setValueInspector = function(val = 0, index = noone) { #region
|
||||||
INLINE
|
INLINE
|
||||||
|
|
||||||
var res = false;
|
var res = false;
|
||||||
val = unit.invApply(val);
|
val = unit.invApply(val);
|
||||||
|
|
||||||
|
@ -2003,27 +1998,32 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
|
||||||
var _node = PANEL_INSPECTOR.inspectings[i];
|
var _node = PANEL_INSPECTOR.inspectings[i];
|
||||||
if(ind >= ds_list_size(_node.inputs)) continue;
|
if(ind >= ds_list_size(_node.inputs)) continue;
|
||||||
|
|
||||||
var r = _node.inputs[| ind].setValueDirect(val, index);
|
var r = _node.inputs[| ind].setValueInspectorDirect(val, index);
|
||||||
if(_node == node) res = r;
|
if(_node == node) res = r;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
res = setValueDirect(val, index);
|
res = setValueInspectorDirect(val, index);
|
||||||
|
|
||||||
//print($"Node {node} : {node.name} {node.internalName}");
|
|
||||||
//print($"Inspecting {PANEL_INSPECTOR.inspecting} : {PANEL_INSPECTOR.inspecting.name} {PANEL_INSPECTOR.inspecting.internalName}");
|
|
||||||
//print($"{node == PANEL_INSPECTOR.inspecting}");
|
|
||||||
//print("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
} #endregion
|
} #endregion
|
||||||
|
|
||||||
|
static setValueInspectorDirect = function(val = 0, index = noone) {
|
||||||
|
if(display_type == VALUE_DISPLAY.d3quarternion && display_data.angle_display == QUARTERNION_DISPLAY.euler) {
|
||||||
|
var _qval = new BBMOD_Quaternion().FromEuler(-val[0], -val[1], -val[2]).ToArray();
|
||||||
|
var _eval = new BBMOD_Quaternion(_qval[0], _qval[1], _qval[2], _qval[3]).ToEuler(true);
|
||||||
|
return setValueDirect(_qval);
|
||||||
|
}
|
||||||
|
|
||||||
|
return setValueDirect(val, index);
|
||||||
|
}
|
||||||
|
|
||||||
static setValueDirect = function(val = 0, index = noone, record = true, time = CURRENT_FRAME, _update = true) { #region
|
static setValueDirect = function(val = 0, index = noone, record = true, time = CURRENT_FRAME, _update = true) { #region
|
||||||
is_modified = true;
|
is_modified = true;
|
||||||
var updated = false;
|
var updated = false;
|
||||||
var _val = val;
|
var _val = val;
|
||||||
var _inp = connect_type == JUNCTION_CONNECT.input;
|
var _inp = connect_type == JUNCTION_CONNECT.input;
|
||||||
|
|
||||||
if(sep_axis) {
|
if(sep_axis) {
|
||||||
if(index == noone) {
|
if(index == noone) {
|
||||||
for( var i = 0, n = array_length(animators); i < n; i++ )
|
for( var i = 0, n = array_length(animators); i < n; i++ )
|
||||||
|
@ -2039,8 +2039,7 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
|
||||||
_val[index] = val;
|
_val[index] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
updated = animator.setValue(_val, _inp && record, time);
|
updated = animator.setValue(_val, _inp && record, time);
|
||||||
//print($"{updated}: {index} - {_val}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type == VALUE_TYPE.gradient) updated = true;
|
if(type == VALUE_TYPE.gradient) updated = true;
|
||||||
|
|
295
#backups/scripts/obj_reader/obj_reader.gml.backup0
Normal file
295
#backups/scripts/obj_reader/obj_reader.gml.backup0
Normal file
|
@ -0,0 +1,295 @@
|
||||||
|
// 2024-05-01 13:45:32
|
||||||
|
function readObj_init(_scale = 1) {
|
||||||
|
obj_reading = true;
|
||||||
|
obj_read_progress = 0;
|
||||||
|
obj_read_prog_sub = 0;
|
||||||
|
obj_read_prog_tot = 3;
|
||||||
|
obj_raw = noone;
|
||||||
|
|
||||||
|
obj_reading_scale = _scale;
|
||||||
|
|
||||||
|
_VB = [];
|
||||||
|
_VBT = [];
|
||||||
|
_VBN = [];
|
||||||
|
mats = [];
|
||||||
|
|
||||||
|
matIndex = [];
|
||||||
|
tris = [];
|
||||||
|
mtlPath = "";
|
||||||
|
use_normal = true;
|
||||||
|
|
||||||
|
v = ds_list_create();
|
||||||
|
vt = ds_list_create();
|
||||||
|
vn = ds_list_create();
|
||||||
|
f = ds_list_create();
|
||||||
|
ft = ds_list_create();
|
||||||
|
fn = ds_list_create();
|
||||||
|
tri = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readObj_file() {
|
||||||
|
var _time = current_time;
|
||||||
|
|
||||||
|
while(!file_text_eof(obj_read_file)) { #region reading file
|
||||||
|
var l = file_text_readln(obj_read_file);
|
||||||
|
l = string_trim(l);
|
||||||
|
|
||||||
|
var sep = string_split(l, " ");
|
||||||
|
if(array_length(sep) == 0) continue;
|
||||||
|
|
||||||
|
switch(sep[0]) {
|
||||||
|
case "v" :
|
||||||
|
ds_list_add(v, [
|
||||||
|
toNumber(sep[1]) * obj_reading_scale,
|
||||||
|
toNumber(sep[2]) * obj_reading_scale,
|
||||||
|
toNumber(sep[3]) * obj_reading_scale
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "vt" :
|
||||||
|
var _u = toNumber(sep[1]);
|
||||||
|
var _v = toNumber(sep[2]);
|
||||||
|
|
||||||
|
ds_list_add(vt, [ _u, _v ]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "vn" :
|
||||||
|
var _nx = toNumber(sep[1]);
|
||||||
|
var _ny = toNumber(sep[2]);
|
||||||
|
var _nz = toNumber(sep[3]);
|
||||||
|
|
||||||
|
ds_list_add(vn, [ _nx, _ny, _nz ]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "f" :
|
||||||
|
var _len = array_length(sep);
|
||||||
|
var _f = array_create(_len - 1);
|
||||||
|
var _ft = array_create(_len - 1);
|
||||||
|
var _fn = array_create(_len - 1);
|
||||||
|
|
||||||
|
for( var i = 1; i < _len; i++ ) {
|
||||||
|
var _sp = string_split(sep[i], "/");
|
||||||
|
if(array_length(_sp) < 3) continue;
|
||||||
|
|
||||||
|
_f[i - 1] = toNumber(_sp[0]);
|
||||||
|
_ft[i - 1] = toNumber(_sp[1]);
|
||||||
|
_fn[i - 1] = toNumber(_sp[2]);
|
||||||
|
|
||||||
|
use_normal = array_length(_sp) >= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
tri += _len - 2;
|
||||||
|
ds_list_add(f, _f ); //get position
|
||||||
|
ds_list_add(ft, _ft); //get texture map
|
||||||
|
ds_list_add(fn, _fn); //get normal
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "usemtl" :
|
||||||
|
var mname = "";
|
||||||
|
for( var i = 1; i < array_length(sep); i++ )
|
||||||
|
mname += (i == 1? "" : " ") + sep[i];
|
||||||
|
mname = string_trim(mname);
|
||||||
|
|
||||||
|
array_push_unique(mats, mname);
|
||||||
|
array_push(matIndex, array_find(mats, mname));
|
||||||
|
|
||||||
|
if(!ds_list_empty(f)) {
|
||||||
|
array_push(_VB, f);
|
||||||
|
array_push(_VBT, ft);
|
||||||
|
array_push(_VBN, fn);
|
||||||
|
array_push(tris, tri);
|
||||||
|
f = ds_list_create();
|
||||||
|
ft = ds_list_create();
|
||||||
|
fn = ds_list_create();
|
||||||
|
}
|
||||||
|
|
||||||
|
tri = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "mtllib" :
|
||||||
|
mtlPath = "";
|
||||||
|
for( var i = 1; i < array_length(sep); i++ )
|
||||||
|
mtlPath += (i == 1? "" : " ") + sep[i];
|
||||||
|
mtlPath = string_trim(mtlPath);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "o" :
|
||||||
|
//print("Reading vertex group: " + sep[1])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(current_time - _time > 30) return;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
if(!ds_list_empty(f)) {
|
||||||
|
array_push(_VB, f);
|
||||||
|
array_push(_VBT, ft);
|
||||||
|
array_push(_VBN, fn);
|
||||||
|
array_push(tris, tri);
|
||||||
|
}
|
||||||
|
file_text_close(obj_read_file);
|
||||||
|
|
||||||
|
if(use_normal) vn[| 0] = [ 0, 0, 0 ];
|
||||||
|
|
||||||
|
obj_read_progress = 1;
|
||||||
|
obj_read_prog_sub = 0;
|
||||||
|
|
||||||
|
//var txt = "OBJ summary";
|
||||||
|
//txt += $"\n\tVerticies : {ds_list_size(v)}";
|
||||||
|
//txt += $"\n\tTexture Verticies : {ds_list_size(vt)}";
|
||||||
|
//txt += $"\n\tNormal Verticies : {ds_list_size(vn)}";
|
||||||
|
//txt += $"\n\tVertex groups : {array_length(_VB)}";
|
||||||
|
//txt += $"\n\tTriangles : {tris}";
|
||||||
|
//print(txt);
|
||||||
|
}
|
||||||
|
|
||||||
|
function readObj_cent() {
|
||||||
|
#region centralize vertex
|
||||||
|
_bmin = v[| 0];
|
||||||
|
_bmax = v[| 0];
|
||||||
|
cv = [0, 0, 0];
|
||||||
|
|
||||||
|
vertex = ds_list_size(v);
|
||||||
|
|
||||||
|
for( var i = 0; i < vertex; i++ ) {
|
||||||
|
var _v = v[| i];
|
||||||
|
var _v0 = _v[0];
|
||||||
|
var _v1 = _v[1];
|
||||||
|
var _v2 = _v[2];
|
||||||
|
|
||||||
|
cv[0] += _v0;
|
||||||
|
cv[1] += _v1;
|
||||||
|
cv[2] += _v2;
|
||||||
|
|
||||||
|
_bmin = [
|
||||||
|
min(_bmin[0], _v0),
|
||||||
|
min(_bmin[1], _v1),
|
||||||
|
min(_bmin[2], _v2),
|
||||||
|
];
|
||||||
|
_bmax = [
|
||||||
|
max(_bmax[0], _v0),
|
||||||
|
max(_bmax[1], _v1),
|
||||||
|
max(_bmax[2], _v2),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
cv[0] /= vertex;
|
||||||
|
cv[1] /= vertex;
|
||||||
|
cv[2] /= vertex;
|
||||||
|
|
||||||
|
obj_size = new __vec3(
|
||||||
|
_bmax[0] - _bmin[0],
|
||||||
|
_bmax[1] - _bmin[1],
|
||||||
|
_bmax[2] - _bmin[2],
|
||||||
|
);
|
||||||
|
|
||||||
|
//print($"{obj_size}");
|
||||||
|
|
||||||
|
var sc = 1;
|
||||||
|
//var span = max(abs(_size.x), abs(_size.y), abs(_size.z));
|
||||||
|
//if(span > 10) sc = span / 10;
|
||||||
|
|
||||||
|
for( var i = 0, n = ds_list_size(v); i < n; i++ ) {
|
||||||
|
v[| i][0] = (v[| i][0] - cv[0]) / sc;
|
||||||
|
v[| i][1] = (v[| i][1] - cv[1]) / sc;
|
||||||
|
v[| i][2] = (v[| i][2] - cv[2]) / sc;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
obj_read_progress = 2;
|
||||||
|
obj_read_prog_sub = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readObj_buff() {
|
||||||
|
#region vertex buffer creation
|
||||||
|
var _vblen = array_length(_VB);
|
||||||
|
var VBS = array_create(_vblen);
|
||||||
|
var V = array_create(_vblen);
|
||||||
|
|
||||||
|
for(var i = 0; i < _vblen; i++) {
|
||||||
|
var VB = vertex_create_buffer();
|
||||||
|
vertex_begin(VB, global.VF_POS_NORM_TEX_COL);
|
||||||
|
var face = _VB[i];
|
||||||
|
var facet = _VBT[i];
|
||||||
|
var facen = _VBN[i];
|
||||||
|
|
||||||
|
var _flen = ds_list_size(face);
|
||||||
|
var _v = ds_list_create();
|
||||||
|
|
||||||
|
for(var j = 0; j < _flen; j++) {
|
||||||
|
var _f = face[| j];
|
||||||
|
var _ft = facet[| j];
|
||||||
|
var _fn = facen[| j];
|
||||||
|
|
||||||
|
var _vlen = array_length(_f);
|
||||||
|
var _pf = array_create(_vlen);
|
||||||
|
var _pft = array_create(_vlen);
|
||||||
|
var _pfn = array_create(_vlen);
|
||||||
|
|
||||||
|
for( var k = 0; k < _vlen; k++ ) {
|
||||||
|
var _vPindex = _f[k] - 1;
|
||||||
|
_pf[k] = v[| _vPindex];
|
||||||
|
|
||||||
|
var _vNindex = _fn[k] - 1;
|
||||||
|
_pfn[k] = vn[| _vNindex];
|
||||||
|
|
||||||
|
var _vTindex = _ft[k] - 1;
|
||||||
|
_pft[k] = vt[| _vTindex];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_vlen >= 3) {
|
||||||
|
vertex_add_pntc(VB, _pf[0], _pfn[0], _pft[0]);
|
||||||
|
vertex_add_pntc(VB, _pf[2], _pfn[2], _pft[2]);
|
||||||
|
vertex_add_pntc(VB, _pf[1], _pfn[1], _pft[1]);
|
||||||
|
|
||||||
|
ds_list_add(_v, new __vertex(_pf[0][0], _pf[0][1], _pf[0][2]).setNormal(_pfn[0][0], _pfn[0][1]).setUV(_pft[0][0], _pft[0][1]));
|
||||||
|
ds_list_add(_v, new __vertex(_pf[2][0], _pf[2][1], _pf[2][2]).setNormal(_pfn[2][0], _pfn[2][1]).setUV(_pft[2][0], _pft[2][1]));
|
||||||
|
ds_list_add(_v, new __vertex(_pf[1][0], _pf[1][1], _pf[1][2]).setNormal(_pfn[1][0], _pfn[1][1]).setUV(_pft[1][0], _pft[1][1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_vlen >= 4) {
|
||||||
|
vertex_add_pntc(VB, _pf[0], _pfn[0], _pft[0]);
|
||||||
|
vertex_add_pntc(VB, _pf[3], _pfn[3], _pft[3]);
|
||||||
|
vertex_add_pntc(VB, _pf[2], _pfn[2], _pft[2]);
|
||||||
|
|
||||||
|
ds_list_add(_v, new __vertex(_pf[0][0], _pf[0][1], _pf[0][2]).setNormal(_pfn[0][0], _pfn[0][1]).setUV(_pft[0][0], _pft[0][1]));
|
||||||
|
ds_list_add(_v, new __vertex(_pf[3][0], _pf[3][1], _pf[3][2]).setNormal(_pfn[3][0], _pfn[3][1]).setUV(_pft[3][0], _pft[3][1]));
|
||||||
|
ds_list_add(_v, new __vertex(_pf[2][0], _pf[2][1], _pf[2][2]).setNormal(_pfn[2][0], _pfn[2][1]).setUV(_pft[2][0], _pft[2][1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vertex_end(VB);
|
||||||
|
vertex_freeze(VB);
|
||||||
|
|
||||||
|
VBS[i] = VB;
|
||||||
|
V[i] = ds_list_to_array(_v);
|
||||||
|
ds_list_destroy(_v);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region clean
|
||||||
|
array_foreach(_VB, function(val, ind) { ds_list_destroy(val); });
|
||||||
|
array_foreach(_VBT, function(val, ind) { ds_list_destroy(val); });
|
||||||
|
array_foreach(_VBN, function(val, ind) { ds_list_destroy(val); });
|
||||||
|
|
||||||
|
ds_list_destroy(v);
|
||||||
|
ds_list_destroy(vn);
|
||||||
|
ds_list_destroy(vt);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
obj_read_progress = 3;
|
||||||
|
obj_read_prog_sub = 0;
|
||||||
|
|
||||||
|
obj_raw = {
|
||||||
|
vertex: V,
|
||||||
|
vertex_count: vertex,
|
||||||
|
vertex_groups: VBS,
|
||||||
|
object_counts: _vblen,
|
||||||
|
|
||||||
|
materials: mats,
|
||||||
|
material_index: matIndex,
|
||||||
|
use_normal: use_normal,
|
||||||
|
mtl_path: mtlPath,
|
||||||
|
model_size: obj_size,
|
||||||
|
};
|
||||||
|
}
|
295
#backups/scripts/obj_reader/obj_reader.gml.backup1
Normal file
295
#backups/scripts/obj_reader/obj_reader.gml.backup1
Normal file
|
@ -0,0 +1,295 @@
|
||||||
|
// 2024-05-01 13:44:23
|
||||||
|
function readObj_init(_scale = 1) {
|
||||||
|
obj_reading = true;
|
||||||
|
obj_read_progress = 0;
|
||||||
|
obj_read_prog_sub = 0;
|
||||||
|
obj_read_prog_tot = 3;
|
||||||
|
obj_raw = noone;
|
||||||
|
|
||||||
|
obj_reading_scale = _scale;
|
||||||
|
|
||||||
|
_VB = [];
|
||||||
|
_VBT = [];
|
||||||
|
_VBN = [];
|
||||||
|
mats = [];
|
||||||
|
|
||||||
|
matIndex = [];
|
||||||
|
tris = [];
|
||||||
|
mtlPath = "";
|
||||||
|
use_normal = true;
|
||||||
|
|
||||||
|
v = ds_list_create();
|
||||||
|
vt = ds_list_create();
|
||||||
|
vn = ds_list_create();
|
||||||
|
f = ds_list_create();
|
||||||
|
ft = ds_list_create();
|
||||||
|
fn = ds_list_create();
|
||||||
|
tri = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readObj_file() {
|
||||||
|
var _time = current_time;
|
||||||
|
|
||||||
|
while(!file_text_eof(obj_read_file)) { #region reading file
|
||||||
|
var l = file_text_readln(obj_read_file);
|
||||||
|
l = string_trim(l);
|
||||||
|
|
||||||
|
var sep = string_split(l, " ");
|
||||||
|
if(array_length(sep) == 0) continue;
|
||||||
|
|
||||||
|
switch(sep[0]) {
|
||||||
|
case "v" :
|
||||||
|
ds_list_add(v, [
|
||||||
|
toNumber(sep[1]) * obj_reading_scale,
|
||||||
|
toNumber(sep[2]) * obj_reading_scale,
|
||||||
|
toNumber(sep[3]) * obj_reading_scale
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "vt" :
|
||||||
|
var _u = toNumber(sep[1]);
|
||||||
|
var _v = toNumber(sep[2]);
|
||||||
|
|
||||||
|
ds_list_add(vt, [ _u, _v ]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "vn" :
|
||||||
|
var _nx = toNumber(sep[1]);
|
||||||
|
var _ny = toNumber(sep[2]);
|
||||||
|
var _nz = toNumber(sep[3]);
|
||||||
|
|
||||||
|
ds_list_add(vn, [ _nx, _ny, _nz ]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "f" :
|
||||||
|
var _len = array_length(sep);
|
||||||
|
var _f = array_create(_len - 1);
|
||||||
|
var _ft = array_create(_len - 1);
|
||||||
|
var _fn = array_create(_len - 1);
|
||||||
|
|
||||||
|
for( var i = 1; i < _len; i++ ) {
|
||||||
|
var _sp = string_split(sep[i], "/");
|
||||||
|
if(array_length(_sp) < 3) continue;
|
||||||
|
|
||||||
|
_f[i - 1] = toNumber(_sp[0]);
|
||||||
|
_ft[i - 1] = toNumber(_sp[1]);
|
||||||
|
_fn[i - 1] = toNumber(_sp[2]);
|
||||||
|
|
||||||
|
use_normal = array_length(_sp) >= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
tri += _len - 2;
|
||||||
|
ds_list_add(f, _f ); //get position
|
||||||
|
ds_list_add(ft, _ft); //get texture map
|
||||||
|
ds_list_add(fn, _fn); //get normal
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "usemtl" :
|
||||||
|
var mname = "";
|
||||||
|
for( var i = 1; i < array_length(sep); i++ )
|
||||||
|
mname += (i == 1? "" : " ") + sep[i];
|
||||||
|
mname = string_trim(mname);
|
||||||
|
|
||||||
|
array_push_unique(mats, mname);
|
||||||
|
array_push(matIndex, array_find(mats, mname));
|
||||||
|
|
||||||
|
if(!ds_list_empty(f)) {
|
||||||
|
array_push(_VB, f);
|
||||||
|
array_push(_VBT, ft);
|
||||||
|
array_push(_VBN, fn);
|
||||||
|
array_push(tris, tri);
|
||||||
|
f = ds_list_create();
|
||||||
|
ft = ds_list_create();
|
||||||
|
fn = ds_list_create();
|
||||||
|
}
|
||||||
|
|
||||||
|
tri = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "mtllib" :
|
||||||
|
mtlPath = "";
|
||||||
|
for( var i = 1; i < array_length(sep); i++ )
|
||||||
|
mtlPath += (i == 1? "" : " ") + sep[i];
|
||||||
|
mtlPath = string_trim(mtlPath);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "o" :
|
||||||
|
//print("Reading vertex group: " + sep[1])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(current_time - _time > 30) return;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
if(!ds_list_empty(f)) {
|
||||||
|
array_push(_VB, f);
|
||||||
|
array_push(_VBT, ft);
|
||||||
|
array_push(_VBN, fn);
|
||||||
|
array_push(tris, tri);
|
||||||
|
}
|
||||||
|
file_text_close(obj_read_file);
|
||||||
|
|
||||||
|
if(use_normal) vn[| 0] = [ 0, 0, 0 ];
|
||||||
|
|
||||||
|
obj_read_progress = 1;
|
||||||
|
obj_read_prog_sub = 0;
|
||||||
|
|
||||||
|
//var txt = "OBJ summary";
|
||||||
|
//txt += $"\n\tVerticies : {ds_list_size(v)}";
|
||||||
|
//txt += $"\n\tTexture Verticies : {ds_list_size(vt)}";
|
||||||
|
//txt += $"\n\tNormal Verticies : {ds_list_size(vn)}";
|
||||||
|
//txt += $"\n\tVertex groups : {array_length(_VB)}";
|
||||||
|
//txt += $"\n\tTriangles : {tris}";
|
||||||
|
//print(txt);
|
||||||
|
}
|
||||||
|
|
||||||
|
function readObj_cent() {
|
||||||
|
#region centralize vertex
|
||||||
|
_bmin = v[| 0];
|
||||||
|
_bmax = v[| 0];
|
||||||
|
cv = [0, 0, 0];
|
||||||
|
|
||||||
|
vertex = ds_list_size(v);
|
||||||
|
|
||||||
|
for( var i = 0; i < vertex; i++ ) {
|
||||||
|
var _v = v[| i];
|
||||||
|
var _v0 = _v[0];
|
||||||
|
var _v1 = _v[1];
|
||||||
|
var _v2 = _v[2];
|
||||||
|
|
||||||
|
cv[0] += _v0;
|
||||||
|
cv[1] += _v1;
|
||||||
|
cv[2] += _v2;
|
||||||
|
|
||||||
|
_bmin = [
|
||||||
|
min(_bmin[0], _v0),
|
||||||
|
min(_bmin[1], _v1),
|
||||||
|
min(_bmin[2], _v2),
|
||||||
|
];
|
||||||
|
_bmax = [
|
||||||
|
max(_bmax[0], _v0),
|
||||||
|
max(_bmax[1], _v1),
|
||||||
|
max(_bmax[2], _v2),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
cv[0] /= vertex;
|
||||||
|
cv[1] /= vertex;
|
||||||
|
cv[2] /= vertex;
|
||||||
|
|
||||||
|
obj_size = new __vec3(
|
||||||
|
_bmax[0] - _bmin[0],
|
||||||
|
_bmax[1] - _bmin[1],
|
||||||
|
_bmax[2] - _bmin[2],
|
||||||
|
);
|
||||||
|
|
||||||
|
print($"{obj_size}");
|
||||||
|
|
||||||
|
var sc = 1;
|
||||||
|
//var span = max(abs(_size.x), abs(_size.y), abs(_size.z));
|
||||||
|
//if(span > 10) sc = span / 10;
|
||||||
|
|
||||||
|
for( var i = 0, n = ds_list_size(v); i < n; i++ ) {
|
||||||
|
v[| i][0] = (v[| i][0] - cv[0]) / sc;
|
||||||
|
v[| i][1] = (v[| i][1] - cv[1]) / sc;
|
||||||
|
v[| i][2] = (v[| i][2] - cv[2]) / sc;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
obj_read_progress = 2;
|
||||||
|
obj_read_prog_sub = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readObj_buff() {
|
||||||
|
#region vertex buffer creation
|
||||||
|
var _vblen = array_length(_VB);
|
||||||
|
var VBS = array_create(_vblen);
|
||||||
|
var V = array_create(_vblen);
|
||||||
|
|
||||||
|
for(var i = 0; i < _vblen; i++) {
|
||||||
|
var VB = vertex_create_buffer();
|
||||||
|
vertex_begin(VB, global.VF_POS_NORM_TEX_COL);
|
||||||
|
var face = _VB[i];
|
||||||
|
var facet = _VBT[i];
|
||||||
|
var facen = _VBN[i];
|
||||||
|
|
||||||
|
var _flen = ds_list_size(face);
|
||||||
|
var _v = ds_list_create();
|
||||||
|
|
||||||
|
for(var j = 0; j < _flen; j++) {
|
||||||
|
var _f = face[| j];
|
||||||
|
var _ft = facet[| j];
|
||||||
|
var _fn = facen[| j];
|
||||||
|
|
||||||
|
var _vlen = array_length(_f);
|
||||||
|
var _pf = array_create(_vlen);
|
||||||
|
var _pft = array_create(_vlen);
|
||||||
|
var _pfn = array_create(_vlen);
|
||||||
|
|
||||||
|
for( var k = 0; k < _vlen; k++ ) {
|
||||||
|
var _vPindex = _f[k] - 1;
|
||||||
|
_pf[k] = v[| _vPindex];
|
||||||
|
|
||||||
|
var _vNindex = _fn[k] - 1;
|
||||||
|
_pfn[k] = vn[| _vNindex];
|
||||||
|
|
||||||
|
var _vTindex = _ft[k] - 1;
|
||||||
|
_pft[k] = vt[| _vTindex];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_vlen >= 3) {
|
||||||
|
vertex_add_pntc(VB, _pf[0], _pfn[0], _pft[0]);
|
||||||
|
vertex_add_pntc(VB, _pf[2], _pfn[2], _pft[2]);
|
||||||
|
vertex_add_pntc(VB, _pf[1], _pfn[1], _pft[1]);
|
||||||
|
|
||||||
|
ds_list_add(_v, new __vertex(_pf[0][0], _pf[0][1], _pf[0][2]).setNormal(_pfn[0][0], _pfn[0][1]).setUV(_pft[0][0], _pft[0][1]));
|
||||||
|
ds_list_add(_v, new __vertex(_pf[2][0], _pf[2][1], _pf[2][2]).setNormal(_pfn[2][0], _pfn[2][1]).setUV(_pft[2][0], _pft[2][1]));
|
||||||
|
ds_list_add(_v, new __vertex(_pf[1][0], _pf[1][1], _pf[1][2]).setNormal(_pfn[1][0], _pfn[1][1]).setUV(_pft[1][0], _pft[1][1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_vlen >= 4) {
|
||||||
|
vertex_add_pntc(VB, _pf[0], _pfn[0], _pft[0]);
|
||||||
|
vertex_add_pntc(VB, _pf[3], _pfn[3], _pft[3]);
|
||||||
|
vertex_add_pntc(VB, _pf[2], _pfn[2], _pft[2]);
|
||||||
|
|
||||||
|
ds_list_add(_v, new __vertex(_pf[0][0], _pf[0][1], _pf[0][2]).setNormal(_pfn[0][0], _pfn[0][1]).setUV(_pft[0][0], _pft[0][1]));
|
||||||
|
ds_list_add(_v, new __vertex(_pf[3][0], _pf[3][1], _pf[3][2]).setNormal(_pfn[3][0], _pfn[3][1]).setUV(_pft[3][0], _pft[3][1]));
|
||||||
|
ds_list_add(_v, new __vertex(_pf[2][0], _pf[2][1], _pf[2][2]).setNormal(_pfn[2][0], _pfn[2][1]).setUV(_pft[2][0], _pft[2][1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vertex_end(VB);
|
||||||
|
vertex_freeze(VB);
|
||||||
|
|
||||||
|
VBS[i] = VB;
|
||||||
|
V[i] = ds_list_to_array(_v);
|
||||||
|
ds_list_destroy(_v);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region clean
|
||||||
|
array_foreach(_VB, function(val, ind) { ds_list_destroy(val); });
|
||||||
|
array_foreach(_VBT, function(val, ind) { ds_list_destroy(val); });
|
||||||
|
array_foreach(_VBN, function(val, ind) { ds_list_destroy(val); });
|
||||||
|
|
||||||
|
ds_list_destroy(v);
|
||||||
|
ds_list_destroy(vn);
|
||||||
|
ds_list_destroy(vt);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
obj_read_progress = 3;
|
||||||
|
obj_read_prog_sub = 0;
|
||||||
|
|
||||||
|
obj_raw = {
|
||||||
|
vertex: V,
|
||||||
|
vertex_count: vertex,
|
||||||
|
vertex_groups: VBS,
|
||||||
|
object_counts: _vblen,
|
||||||
|
|
||||||
|
materials: mats,
|
||||||
|
material_index: matIndex,
|
||||||
|
use_normal: use_normal,
|
||||||
|
mtl_path: mtlPath,
|
||||||
|
model_size: obj_size,
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// 2024-04-30 16:02:42
|
// 2024-05-01 09:02:09
|
||||||
#region funtion calls
|
#region funtion calls
|
||||||
function __fnInit_Graph() {
|
function __fnInit_Graph() {
|
||||||
__registerFunction("graph_add_node", panel_graph_add_node);
|
__registerFunction("graph_add_node", panel_graph_add_node);
|
||||||
|
@ -167,7 +167,7 @@ function Panel_Graph(project = PROJECT) : PanelContent() constructor {
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ---- position ----
|
#region ---- position ----
|
||||||
scale = [ 0.01, 0.02, 0.05, 0.10, 0.15, 0.20, 0.25, 0.33, 0.50, 0.65, 0.80, 1, 1.2, 1.35, 1.5, 2.0];
|
scale = [ 0.01, 0.02, 0.05, 0.10, 0.15, 0.20, 0.25, 0.33, 0.50, 0.65, 0.80, 1, 1.2, 1.35, 1.5, 2.0 ];
|
||||||
graph_s = 1;
|
graph_s = 1;
|
||||||
graph_s_to = graph_s;
|
graph_s_to = graph_s;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// 2024-04-30 15:49:15
|
// 2024-05-01 08:49:36
|
||||||
#region funtion calls
|
#region funtion calls
|
||||||
function __fnInit_Graph() {
|
function __fnInit_Graph() {
|
||||||
__registerFunction("graph_add_node", panel_graph_add_node);
|
__registerFunction("graph_add_node", panel_graph_add_node);
|
||||||
|
@ -167,7 +167,7 @@ function Panel_Graph(project = PROJECT) : PanelContent() constructor {
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ---- position ----
|
#region ---- position ----
|
||||||
scale = [ 0.01, 0.02, 0.05, 0.10, 0.15, 0.20, 0.25, 0.33, 0.50, 0.65, 0.80, 1, 1.2, 1.35, 1.5, 2.0];
|
scale = [ 0.01, 0.02, 0.05, 0.10, 0.15, 0.20, 0.25, 0.33, 0.50, 0.65, 0.80, 1, 1.2, 1.35, 1.5, 2.0 ];
|
||||||
graph_s = 1;
|
graph_s = 1;
|
||||||
graph_s_to = graph_s;
|
graph_s_to = graph_s;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// 2024-04-30 13:08:35
|
// 2024-05-01 16:14:03
|
||||||
#region funtion calls
|
#region funtion calls
|
||||||
function __fnInit_Preview() {
|
function __fnInit_Preview() {
|
||||||
__registerFunction("preview_focus_content", panel_preview_focus_content);
|
__registerFunction("preview_focus_content", panel_preview_focus_content);
|
||||||
|
@ -927,7 +927,7 @@ function Panel_Preview() : PanelContent() constructor {
|
||||||
|
|
||||||
#region defer
|
#region defer
|
||||||
var _prev_obj = _prev_node.getPreviewObject();
|
var _prev_obj = _prev_node.getPreviewObject();
|
||||||
d3_deferData = d3_scene_preview.deferPass(_prev_obj, w, h, d3_deferData);
|
if(_prev_obj) d3_deferData = d3_scene_preview.deferPass(_prev_obj, w, h, d3_deferData);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region grid
|
#region grid
|
||||||
|
@ -1504,6 +1504,7 @@ function Panel_Preview() : PanelContent() constructor {
|
||||||
}
|
}
|
||||||
|
|
||||||
wdg.setFocusHover(pFOCUS, pHOVER);
|
wdg.setFocusHover(pFOCUS, pHOVER);
|
||||||
|
var _tool_font = f_p3;
|
||||||
|
|
||||||
switch(instanceof(wdg)) {
|
switch(instanceof(wdg)) {
|
||||||
case "textBox" :
|
case "textBox" :
|
||||||
|
@ -1512,16 +1513,27 @@ function Panel_Preview() : PanelContent() constructor {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "buttonGroup":
|
case "buttonGroup":
|
||||||
case "checkBoxGroup" : tolw = tolh * wdg.size; break;
|
case "checkBoxGroup" :
|
||||||
|
tolw = tolh * wdg.size;
|
||||||
|
break;
|
||||||
|
|
||||||
case "checkBox" : tolw = tolh; break;
|
case "checkBox" :
|
||||||
case "scrollBox" : tolw = ui(96); break;
|
tolw = tolh;
|
||||||
case "buttonClass" : tolw = wdg.text == ""? tolh : tolw; break;
|
break;
|
||||||
|
|
||||||
|
case "scrollBox" :
|
||||||
|
tolw = ui(96);
|
||||||
|
_tool_font = f_p2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "buttonClass" :
|
||||||
|
tolw = wdg.text == ""? tolh : tolw;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var params = new widgetParam(tolx, toly, tolw, tolh, atr[$ key],, [ mx, my ])
|
var params = new widgetParam(tolx, toly, tolw, tolh, atr[$ key],, [ mx, my ])
|
||||||
params.s = tolh;
|
params.s = tolh;
|
||||||
params.font = f_p3;
|
params.font = _tool_font;
|
||||||
|
|
||||||
wdg.drawParam(params);
|
wdg.drawParam(params);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// 2024-04-30 13:08:33
|
// 2024-05-01 16:14:02
|
||||||
#region funtion calls
|
#region funtion calls
|
||||||
function __fnInit_Preview() {
|
function __fnInit_Preview() {
|
||||||
__registerFunction("preview_focus_content", panel_preview_focus_content);
|
__registerFunction("preview_focus_content", panel_preview_focus_content);
|
||||||
|
@ -927,7 +927,7 @@ function Panel_Preview() : PanelContent() constructor {
|
||||||
|
|
||||||
#region defer
|
#region defer
|
||||||
var _prev_obj = _prev_node.getPreviewObject();
|
var _prev_obj = _prev_node.getPreviewObject();
|
||||||
d3_deferData = d3_scene_preview.deferPass(_prev_obj, w, h, d3_deferData);
|
if(_prev_obj) d3_deferData = d3_scene_preview.deferPass(_prev_obj, w, h, d3_deferData);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region grid
|
#region grid
|
||||||
|
@ -1504,6 +1504,7 @@ function Panel_Preview() : PanelContent() constructor {
|
||||||
}
|
}
|
||||||
|
|
||||||
wdg.setFocusHover(pFOCUS, pHOVER);
|
wdg.setFocusHover(pFOCUS, pHOVER);
|
||||||
|
var _tool_font = f_p3;
|
||||||
|
|
||||||
switch(instanceof(wdg)) {
|
switch(instanceof(wdg)) {
|
||||||
case "textBox" :
|
case "textBox" :
|
||||||
|
@ -1512,16 +1513,27 @@ function Panel_Preview() : PanelContent() constructor {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "buttonGroup":
|
case "buttonGroup":
|
||||||
case "checkBoxGroup" : tolw = tolh * wdg.size; break;
|
case "checkBoxGroup" :
|
||||||
|
tolw = tolh * wdg.size;
|
||||||
|
break;
|
||||||
|
|
||||||
case "checkBox" : tolw = tolh; break;
|
case "checkBox" :
|
||||||
case "scrollBox" : tolw = ui(96); break;
|
tolw = tolh;
|
||||||
case "buttonClass" : tolw = wdg.text == ""? tolh : tolw; break;
|
break;
|
||||||
|
|
||||||
|
case "scrollBox" :
|
||||||
|
tolw = ui(96);
|
||||||
|
_tool_font = f_p2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "buttonClass" :
|
||||||
|
tolw = wdg.text == ""? tolh : tolw;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var params = new widgetParam(tolx, toly, tolw, tolh, atr[$ key],, [ mx, my ])
|
var params = new widgetParam(tolx, toly, tolw, tolh, atr[$ key],, [ mx, my ])
|
||||||
params.s = tolh;
|
params.s = tolh;
|
||||||
params.font = f_p3;
|
params.font = _tool_font;
|
||||||
|
|
||||||
wdg.drawParam(params);
|
wdg.drawParam(params);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// 2024-04-29 18:32:52
|
// 2024-05-01 16:00:48
|
||||||
#region preference
|
#region preference
|
||||||
globalvar PREFERENCES, PREFERENCES_DEF, HOTKEYS_DATA;
|
globalvar PREFERENCES, PREFERENCES_DEF, HOTKEYS_DATA;
|
||||||
PREFERENCES = {};
|
PREFERENCES = {};
|
||||||
|
@ -114,6 +114,7 @@
|
||||||
|
|
||||||
PREFERENCES.node_param_show = false;
|
PREFERENCES.node_param_show = false;
|
||||||
PREFERENCES.node_param_width = 192;
|
PREFERENCES.node_param_width = 192;
|
||||||
|
PREFERENCES.node_3d_preview_size = 256;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// 2024-04-28 08:01:20
|
// 2024-05-01 15:57:54
|
||||||
#region preference
|
#region preference
|
||||||
globalvar PREFERENCES, PREFERENCES_DEF, HOTKEYS_DATA;
|
globalvar PREFERENCES, PREFERENCES_DEF, HOTKEYS_DATA;
|
||||||
PREFERENCES = {};
|
PREFERENCES = {};
|
||||||
|
@ -114,6 +114,7 @@
|
||||||
|
|
||||||
PREFERENCES.node_param_show = false;
|
PREFERENCES.node_param_show = false;
|
||||||
PREFERENCES.node_param_width = 192;
|
PREFERENCES.node_param_width = 192;
|
||||||
|
PREFERENCES.node_3d_preview_size = 256;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
151
#backups/scripts/quarternionBox/quarternionBox.gml.backup0
Normal file
151
#backups/scripts/quarternionBox/quarternionBox.gml.backup0
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
// 2024-05-01 17:23:09
|
||||||
|
enum QUARTERNION_DISPLAY {
|
||||||
|
quarterion,
|
||||||
|
euler,
|
||||||
|
}
|
||||||
|
|
||||||
|
function quarternionBox(_onModify) : widget() constructor {
|
||||||
|
onModify = _onModify;
|
||||||
|
current_value = [ 0, 0, 0, 0 ];
|
||||||
|
current_unit = QUARTERNION_DISPLAY.quarterion;
|
||||||
|
|
||||||
|
onModifyIndex = function(index, val) {
|
||||||
|
var v = toNumber(val);
|
||||||
|
|
||||||
|
if(current_unit == QUARTERNION_DISPLAY.quarterion) {
|
||||||
|
return onModify(index, v);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
var v = toNumber(val);
|
||||||
|
var qv = [
|
||||||
|
current_value[0],
|
||||||
|
current_value[1],
|
||||||
|
current_value[2],
|
||||||
|
];
|
||||||
|
|
||||||
|
qv[index] = v;
|
||||||
|
return onModify(noone, qv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size = 4;
|
||||||
|
axis = [ "x", "y", "z", "w" ];
|
||||||
|
tooltip = new tooltipSelector("Angle type", [__txt("Quaternion"), __txt("Euler")]);
|
||||||
|
|
||||||
|
disp_w = noone;
|
||||||
|
clickable = true;
|
||||||
|
|
||||||
|
onModifySingle[0] = function(val) { return onModifyIndex(0, val); }
|
||||||
|
onModifySingle[1] = function(val) { return onModifyIndex(1, val); }
|
||||||
|
onModifySingle[2] = function(val) { return onModifyIndex(2, val); }
|
||||||
|
onModifySingle[3] = function(val) { return onModifyIndex(3, val); }
|
||||||
|
|
||||||
|
for(var i = 0; i < 4; i++) {
|
||||||
|
tb[i] = new textBox(TEXTBOX_INPUT.number, onModifySingle[i]);
|
||||||
|
tb[i].slidable = true;
|
||||||
|
tb[i].label = axis[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
static setSlideSpeed = function(speed) {
|
||||||
|
for(var i = 0; i < size; i++)
|
||||||
|
tb[i].setSlidable(speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static setInteract = function(interactable) {
|
||||||
|
self.interactable = interactable;
|
||||||
|
|
||||||
|
for( var i = 0; i < size; i++ )
|
||||||
|
tb[i].interactable = interactable;
|
||||||
|
}
|
||||||
|
|
||||||
|
static register = function(parent = noone) {
|
||||||
|
for( var i = 0; i < size; i++ )
|
||||||
|
tb[i].register(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static isHovering = function() {
|
||||||
|
for( var i = 0, n = array_length(tb); i < n; i++ ) if(tb[i].isHovering()) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static apply = function() {
|
||||||
|
for( var i = 0; i < size; i++ ) {
|
||||||
|
tb[i].apply();
|
||||||
|
current_value[i] = toNumber(tb[i]._input_text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static drawParam = function(params) {
|
||||||
|
setParam(params);
|
||||||
|
for(var i = 0; i < 4; i++) tb[i].setParam(params);
|
||||||
|
|
||||||
|
return draw(params.x, params.y, params.w, params.h, params.data, params.display_data, params.m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static draw = function(_x, _y, _w, _h, _data, _display_data, _m) {
|
||||||
|
x = _x;
|
||||||
|
y = _y;
|
||||||
|
w = _w;
|
||||||
|
h = _h;
|
||||||
|
|
||||||
|
if(!is_array(_data)) return 0;
|
||||||
|
if(array_empty(_data)) return 0;
|
||||||
|
if(is_array(_data[0])) return 0;
|
||||||
|
|
||||||
|
var _bs = min(_h, ui(32));
|
||||||
|
var _disp = struct_try_get(_display_data, "angle_display");
|
||||||
|
|
||||||
|
if((_w - _bs) / 2 > ui(64)) {
|
||||||
|
var bx = _x + _w - _bs;
|
||||||
|
var by = _y + _h / 2 - _bs / 2;
|
||||||
|
tooltip.index = _disp;
|
||||||
|
|
||||||
|
if(buttonInstant(THEME.button_hide, bx, by, _bs, _bs, _m, iactive, ihover, tooltip, THEME.unit_angle, _disp, c_white) == 2) {
|
||||||
|
clickable = false;
|
||||||
|
_display_data.angle_display = (_disp + 1) % 2;
|
||||||
|
}
|
||||||
|
_w -= _bs + ui(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
current_unit = _display_data.angle_display;
|
||||||
|
|
||||||
|
if(current_unit == QUARTERNION_DISPLAY.quarterion || (!tb[0].sliding && !tb[1].sliding && !tb[2].sliding)) {
|
||||||
|
current_value[0] = _data[0];
|
||||||
|
current_value[1] = _data[1];
|
||||||
|
current_value[2] = _data[2];
|
||||||
|
|
||||||
|
if(current_unit == QUARTERNION_DISPLAY.quarterion)
|
||||||
|
current_value[3] = _data[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
size = _disp? 3 : 4;
|
||||||
|
var ww = _w / size;
|
||||||
|
var bx = _x;
|
||||||
|
disp_w = disp_w == noone? ww : lerp_float(disp_w, ww, 3);
|
||||||
|
|
||||||
|
var _dispDat = _data;
|
||||||
|
|
||||||
|
draw_sprite_stretched_ext(THEME.textbox, 3, _x, _y, _w, _h, c_white, 1);
|
||||||
|
draw_sprite_stretched_ext(THEME.textbox, 0, _x, _y, _w, _h, c_white, 0.5 + 0.5 * interactable);
|
||||||
|
|
||||||
|
for(var i = 0; i < size; i++) {
|
||||||
|
var _a = _dispDat[i];
|
||||||
|
|
||||||
|
tb[i].hide = true;
|
||||||
|
tb[i].setFocusHover(clickable && active, hover);
|
||||||
|
tb[i].draw(bx, _y, disp_w, _h, _a, _m);
|
||||||
|
|
||||||
|
bx += disp_w;
|
||||||
|
}
|
||||||
|
|
||||||
|
clickable = true;
|
||||||
|
resetFocus();
|
||||||
|
|
||||||
|
return _h;
|
||||||
|
}
|
||||||
|
|
||||||
|
static clone = function() { #region
|
||||||
|
var cln = new quarternionBox(onModify);
|
||||||
|
return cln;
|
||||||
|
} #endregion
|
||||||
|
}
|
152
#backups/scripts/quarternionBox/quarternionBox.gml.backup1
Normal file
152
#backups/scripts/quarternionBox/quarternionBox.gml.backup1
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
// 2024-05-01 17:22:26
|
||||||
|
enum QUARTERNION_DISPLAY {
|
||||||
|
quarterion,
|
||||||
|
euler,
|
||||||
|
}
|
||||||
|
|
||||||
|
function quarternionBox(_onModify) : widget() constructor {
|
||||||
|
onModify = _onModify;
|
||||||
|
current_value = [ 0, 0, 0, 0 ];
|
||||||
|
current_unit = QUARTERNION_DISPLAY.quarterion;
|
||||||
|
|
||||||
|
onModifyIndex = function(index, val) {
|
||||||
|
var v = toNumber(val);
|
||||||
|
|
||||||
|
if(current_unit == QUARTERNION_DISPLAY.quarterion) {
|
||||||
|
return onModify(index, v);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
var v = toNumber(val);
|
||||||
|
var qv = [
|
||||||
|
current_value[0],
|
||||||
|
current_value[1],
|
||||||
|
current_value[2],
|
||||||
|
];
|
||||||
|
|
||||||
|
qv[index] = v;
|
||||||
|
print(qv);
|
||||||
|
return onModify(noone, qv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size = 4;
|
||||||
|
axis = [ "x", "y", "z", "w" ];
|
||||||
|
tooltip = new tooltipSelector("Angle type", [__txt("Quaternion"), __txt("Euler")]);
|
||||||
|
|
||||||
|
disp_w = noone;
|
||||||
|
clickable = true;
|
||||||
|
|
||||||
|
onModifySingle[0] = function(val) { return onModifyIndex(0, val); }
|
||||||
|
onModifySingle[1] = function(val) { return onModifyIndex(1, val); }
|
||||||
|
onModifySingle[2] = function(val) { return onModifyIndex(2, val); }
|
||||||
|
onModifySingle[3] = function(val) { return onModifyIndex(3, val); }
|
||||||
|
|
||||||
|
for(var i = 0; i < 4; i++) {
|
||||||
|
tb[i] = new textBox(TEXTBOX_INPUT.number, onModifySingle[i]);
|
||||||
|
tb[i].slidable = true;
|
||||||
|
tb[i].label = axis[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
static setSlideSpeed = function(speed) {
|
||||||
|
for(var i = 0; i < size; i++)
|
||||||
|
tb[i].setSlidable(speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static setInteract = function(interactable) {
|
||||||
|
self.interactable = interactable;
|
||||||
|
|
||||||
|
for( var i = 0; i < size; i++ )
|
||||||
|
tb[i].interactable = interactable;
|
||||||
|
}
|
||||||
|
|
||||||
|
static register = function(parent = noone) {
|
||||||
|
for( var i = 0; i < size; i++ )
|
||||||
|
tb[i].register(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static isHovering = function() {
|
||||||
|
for( var i = 0, n = array_length(tb); i < n; i++ ) if(tb[i].isHovering()) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static apply = function() {
|
||||||
|
for( var i = 0; i < size; i++ ) {
|
||||||
|
tb[i].apply();
|
||||||
|
current_value[i] = toNumber(tb[i]._input_text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static drawParam = function(params) {
|
||||||
|
setParam(params);
|
||||||
|
for(var i = 0; i < 4; i++) tb[i].setParam(params);
|
||||||
|
|
||||||
|
return draw(params.x, params.y, params.w, params.h, params.data, params.display_data, params.m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static draw = function(_x, _y, _w, _h, _data, _display_data, _m) {
|
||||||
|
x = _x;
|
||||||
|
y = _y;
|
||||||
|
w = _w;
|
||||||
|
h = _h;
|
||||||
|
|
||||||
|
if(!is_array(_data)) return 0;
|
||||||
|
if(array_empty(_data)) return 0;
|
||||||
|
if(is_array(_data[0])) return 0;
|
||||||
|
|
||||||
|
var _bs = min(_h, ui(32));
|
||||||
|
var _disp = struct_try_get(_display_data, "angle_display");
|
||||||
|
|
||||||
|
if((_w - _bs) / 2 > ui(64)) {
|
||||||
|
var bx = _x + _w - _bs;
|
||||||
|
var by = _y + _h / 2 - _bs / 2;
|
||||||
|
tooltip.index = _disp;
|
||||||
|
|
||||||
|
if(buttonInstant(THEME.button_hide, bx, by, _bs, _bs, _m, iactive, ihover, tooltip, THEME.unit_angle, _disp, c_white) == 2) {
|
||||||
|
clickable = false;
|
||||||
|
_display_data.angle_display = (_disp + 1) % 2;
|
||||||
|
}
|
||||||
|
_w -= _bs + ui(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
current_unit = _display_data.angle_display;
|
||||||
|
|
||||||
|
if(current_unit == QUARTERNION_DISPLAY.quarterion || (!tb[0].sliding && !tb[1].sliding && !tb[2].sliding)) {
|
||||||
|
current_value[0] = _data[0];
|
||||||
|
current_value[1] = _data[1];
|
||||||
|
current_value[2] = _data[2];
|
||||||
|
|
||||||
|
if(current_unit == QUARTERNION_DISPLAY.quarterion)
|
||||||
|
current_value[3] = _data[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
size = _disp? 3 : 4;
|
||||||
|
var ww = _w / size;
|
||||||
|
var bx = _x;
|
||||||
|
disp_w = disp_w == noone? ww : lerp_float(disp_w, ww, 3);
|
||||||
|
|
||||||
|
var _dispDat = _data;
|
||||||
|
|
||||||
|
draw_sprite_stretched_ext(THEME.textbox, 3, _x, _y, _w, _h, c_white, 1);
|
||||||
|
draw_sprite_stretched_ext(THEME.textbox, 0, _x, _y, _w, _h, c_white, 0.5 + 0.5 * interactable);
|
||||||
|
|
||||||
|
for(var i = 0; i < size; i++) {
|
||||||
|
var _a = _dispDat[i];
|
||||||
|
|
||||||
|
tb[i].hide = true;
|
||||||
|
tb[i].setFocusHover(clickable && active, hover);
|
||||||
|
tb[i].draw(bx, _y, disp_w, _h, _a, _m);
|
||||||
|
|
||||||
|
bx += disp_w;
|
||||||
|
}
|
||||||
|
|
||||||
|
clickable = true;
|
||||||
|
resetFocus();
|
||||||
|
|
||||||
|
return _h;
|
||||||
|
}
|
||||||
|
|
||||||
|
static clone = function() { #region
|
||||||
|
var cln = new quarternionBox(onModify);
|
||||||
|
return cln;
|
||||||
|
} #endregion
|
||||||
|
}
|
51
#backups/scripts/shell_functions/shell_functions.gml.backup0
Normal file
51
#backups/scripts/shell_functions/shell_functions.gml.backup0
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
// 2024-05-01 11:40:21
|
||||||
|
function shellOpenExplorer(path) { #region
|
||||||
|
if(OS == os_windows) {
|
||||||
|
var _windir = environment_get_variable("WINDIR") + "/explorer.exe";
|
||||||
|
path = string_replace_all(path, "/", "\\");
|
||||||
|
shell_execute_async(_windir, path);
|
||||||
|
} else if(OS == os_macosx) {
|
||||||
|
path = string_replace_all(path, "\\", "/");
|
||||||
|
var res = shell_execute_async("open", path);
|
||||||
|
}
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
function shell_execute(path, command, ref = noone) { #region
|
||||||
|
INLINE
|
||||||
|
|
||||||
|
if(OS == os_macosx) {
|
||||||
|
path = string_replace_all(path, "\\", "/");
|
||||||
|
command = string_replace_all(command, "\\", "/");
|
||||||
|
}
|
||||||
|
|
||||||
|
var txt = $"{path} {command}";
|
||||||
|
var res = ProcessExecute(txt);
|
||||||
|
print($"Execute {path} {command} | {res}");
|
||||||
|
|
||||||
|
return res;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
function shell_execute_async(path, command, ref = noone, _log = true) { #region
|
||||||
|
INLINE
|
||||||
|
|
||||||
|
if(IS_CMD) return shell_execute(path, command, ref);
|
||||||
|
|
||||||
|
if(OS == os_macosx) {
|
||||||
|
path = string_replace_all(path, "\\", "/");
|
||||||
|
command = string_replace_all(command, "\\", "/");
|
||||||
|
}
|
||||||
|
|
||||||
|
var txt = $"{path} {command}";
|
||||||
|
var res = ProcessExecuteAsync(txt);
|
||||||
|
if(_log) print($"Execute async {path} {command} | {res}");
|
||||||
|
|
||||||
|
return res;
|
||||||
|
} #endregion
|
||||||
|
|
||||||
|
function env_user() { #region
|
||||||
|
INLINE
|
||||||
|
|
||||||
|
if(OS == os_windows) return string(environment_get_variable("userprofile")) + "\\AppData\\Local\\PixelComposer\\";
|
||||||
|
if(OS == os_macosx) return string(environment_get_variable("HOME")) + "/PixelComposer/";
|
||||||
|
return "";
|
||||||
|
} #endregion
|
|
@ -1,4 +1,4 @@
|
||||||
// 2024-04-16 08:41:19
|
// 2024-05-01 11:31:11
|
||||||
function string_to_array(str) { #region
|
function string_to_array(str) { #region
|
||||||
var amo = string_length(str);
|
var amo = string_length(str);
|
||||||
var arr = array_create(amo);
|
var arr = array_create(amo);
|
||||||
|
@ -66,12 +66,5 @@ function filename_name_only(name) { #region
|
||||||
return string_replace(name, filename_ext(name), "")
|
return string_replace(name, filename_ext(name), "")
|
||||||
} #endregion
|
} #endregion
|
||||||
|
|
||||||
function string_to_var(str) { #region
|
function string_to_var(str) { INLINE return string_replace_all(string_lower(str), " ", "_"); }
|
||||||
INLINE
|
function string_quote(str) { INLINE return $"\"{str}\""; }
|
||||||
return string_replace_all(string_lower(str), " ", "_");
|
|
||||||
} #endregion
|
|
||||||
|
|
||||||
function string_quote(str) { #region
|
|
||||||
INLINE
|
|
||||||
return $"\"{str}\"";
|
|
||||||
} #endregion
|
|
|
@ -1,4 +1,4 @@
|
||||||
// 2024-04-16 08:29:49
|
// 2024-05-01 11:29:46
|
||||||
function string_to_array(str) { #region
|
function string_to_array(str) { #region
|
||||||
var amo = string_length(str);
|
var amo = string_length(str);
|
||||||
var arr = array_create(amo);
|
var arr = array_create(amo);
|
||||||
|
@ -66,12 +66,5 @@ function filename_name_only(name) { #region
|
||||||
return string_replace(name, filename_ext(name), "")
|
return string_replace(name, filename_ext(name), "")
|
||||||
} #endregion
|
} #endregion
|
||||||
|
|
||||||
function string_to_var(str) { #region
|
function string_to_var(str) { INLINE return string_replace_all(string_lower(str), " ", "_"); }
|
||||||
INLINE
|
function string_quote(str) { INLINE return $"\"{str}\""; }
|
||||||
return string_replace_all(string_lower(str), " ", "_");
|
|
||||||
} #endregion
|
|
||||||
|
|
||||||
function string_quote(str) { #region
|
|
||||||
INLINE
|
|
||||||
return $"\"{str}\"";
|
|
||||||
} #endregion
|
|
|
@ -1,4 +1,4 @@
|
||||||
// 2024-04-18 13:00:44
|
// 2024-05-01 11:57:36
|
||||||
enum TEXTBOX_INPUT {
|
enum TEXTBOX_INPUT {
|
||||||
text,
|
text,
|
||||||
number
|
number
|
||||||
|
@ -7,9 +7,9 @@ enum TEXTBOX_INPUT {
|
||||||
function textBox(_input, _onModify) : textInput(_input, _onModify) constructor {
|
function textBox(_input, _onModify) : textInput(_input, _onModify) constructor {
|
||||||
onRelease = noone;
|
onRelease = noone;
|
||||||
|
|
||||||
align = _input == TEXTBOX_INPUT.number? fa_center : fa_left;
|
align = _input == TEXTBOX_INPUT.number? fa_center : fa_left;
|
||||||
hide = false;
|
hide = false;
|
||||||
color = COLORS._main_text;
|
color = COLORS._main_text;
|
||||||
boxColor = c_white;
|
boxColor = c_white;
|
||||||
format = TEXT_AREA_FORMAT._default;
|
format = TEXT_AREA_FORMAT._default;
|
||||||
precision = 5;
|
precision = 5;
|
||||||
|
@ -498,8 +498,10 @@ function textBox(_input, _onModify) : textInput(_input, _onModify) constructor {
|
||||||
draw_set_alpha(1);
|
draw_set_alpha(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _dpx = disp_x;
|
||||||
disp_x = lerp_float(disp_x, disp_x_to, 5);
|
disp_x = lerp_float(disp_x, disp_x_to, 5);
|
||||||
|
if(_dpx != disp_x) _update = true;
|
||||||
|
|
||||||
var hoverRect = point_in_rectangle(_m[0], _m[1], _x, _y, _x + _w, _y + _h);
|
var hoverRect = point_in_rectangle(_m[0], _m[1], _x, _y, _x + _w, _y + _h);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// 2024-04-18 13:00:36
|
// 2024-05-01 11:57:26
|
||||||
enum TEXTBOX_INPUT {
|
enum TEXTBOX_INPUT {
|
||||||
text,
|
text,
|
||||||
number
|
number
|
||||||
|
@ -7,9 +7,9 @@ enum TEXTBOX_INPUT {
|
||||||
function textBox(_input, _onModify) : textInput(_input, _onModify) constructor {
|
function textBox(_input, _onModify) : textInput(_input, _onModify) constructor {
|
||||||
onRelease = noone;
|
onRelease = noone;
|
||||||
|
|
||||||
align = _input == TEXTBOX_INPUT.number? fa_center : fa_left;
|
align = _input == TEXTBOX_INPUT.number? fa_center : fa_left;
|
||||||
hide = false;
|
hide = false;
|
||||||
color = COLORS._main_text;
|
color = COLORS._main_text;
|
||||||
boxColor = c_white;
|
boxColor = c_white;
|
||||||
format = TEXT_AREA_FORMAT._default;
|
format = TEXT_AREA_FORMAT._default;
|
||||||
precision = 5;
|
precision = 5;
|
||||||
|
@ -498,8 +498,10 @@ function textBox(_input, _onModify) : textInput(_input, _onModify) constructor {
|
||||||
draw_set_alpha(1);
|
draw_set_alpha(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _dpx = disp_x;
|
||||||
disp_x = lerp_float(disp_x, disp_x_to, 5);
|
disp_x = lerp_float(disp_x, disp_x_to, 5);
|
||||||
|
if(_dpx != disp_x) _update = true;
|
||||||
|
|
||||||
var hoverRect = point_in_rectangle(_m[0], _m[1], _x, _y, _x + _w, _y + _h);
|
var hoverRect = point_in_rectangle(_m[0], _m[1], _x, _y, _x + _w, _y + _h);
|
||||||
|
|
||||||
|
|
|
@ -551,6 +551,17 @@ event_inherited();
|
||||||
PREF_SAVE();
|
PREF_SAVE();
|
||||||
})
|
})
|
||||||
));
|
));
|
||||||
|
|
||||||
|
ds_list_add(pref_node, new __Panel_Linear_Setting_Item_Preference(
|
||||||
|
__txtx("pref_node_3d_preview", "Preview surface size"),
|
||||||
|
"node_3d_preview_size",
|
||||||
|
|
||||||
|
new textBox(TEXTBOX_INPUT.number, function(val) {
|
||||||
|
PREFERENCES.node_3d_preview_size = clamp(val, 16, 1024);
|
||||||
|
PREF_SAVE();
|
||||||
|
})
|
||||||
|
));
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region theme
|
#region theme
|
||||||
|
|
|
@ -2,110 +2,112 @@
|
||||||
if(winMan_isMinimized()) exit;
|
if(winMan_isMinimized()) exit;
|
||||||
|
|
||||||
#region tooltip
|
#region tooltip
|
||||||
if(is_struct(TOOLTIP)) {
|
if(!_MOUSE_BLOCK) {
|
||||||
if(struct_has(TOOLTIP, "drawTooltip"))
|
if(is_struct(TOOLTIP)) {
|
||||||
TOOLTIP.drawTooltip();
|
if(struct_has(TOOLTIP, "drawTooltip"))
|
||||||
|
TOOLTIP.drawTooltip();
|
||||||
} else if(is_array(TOOLTIP)) {
|
|
||||||
var content = TOOLTIP[0];
|
|
||||||
var type = TOOLTIP[1];
|
|
||||||
|
|
||||||
if(is_method(content)) content = content();
|
|
||||||
|
|
||||||
switch(type) {
|
|
||||||
case VALUE_TYPE.float :
|
|
||||||
case VALUE_TYPE.integer :
|
|
||||||
case VALUE_TYPE.text :
|
|
||||||
case VALUE_TYPE.struct :
|
|
||||||
case VALUE_TYPE.path :
|
|
||||||
draw_tooltip_text(string_real(content));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VALUE_TYPE.boolean :
|
} else if(is_array(TOOLTIP)) {
|
||||||
draw_tooltip_text(printBool(content));
|
var content = TOOLTIP[0];
|
||||||
break;
|
var type = TOOLTIP[1];
|
||||||
|
|
||||||
case VALUE_TYPE.curve :
|
if(is_method(content)) content = content();
|
||||||
draw_tooltip_text("[" + __txt("Curve Object") + "]");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VALUE_TYPE.color :
|
switch(type) {
|
||||||
draw_tooltip_color(content);
|
case VALUE_TYPE.float :
|
||||||
break;
|
case VALUE_TYPE.integer :
|
||||||
|
case VALUE_TYPE.text :
|
||||||
case VALUE_TYPE.gradient :
|
case VALUE_TYPE.struct :
|
||||||
draw_tooltip_gradient(content);
|
case VALUE_TYPE.path :
|
||||||
break;
|
draw_tooltip_text(string_real(content));
|
||||||
|
break;
|
||||||
case VALUE_TYPE.d3object :
|
|
||||||
draw_tooltip_text("[" + __txt("3D Object") + "]");
|
case VALUE_TYPE.boolean :
|
||||||
break;
|
draw_tooltip_text(printBool(content));
|
||||||
|
break;
|
||||||
case VALUE_TYPE.object :
|
|
||||||
draw_tooltip_text("[" + __txt("Object") + "]");
|
case VALUE_TYPE.curve :
|
||||||
break;
|
draw_tooltip_text("[" + __txt("Curve Object") + "]");
|
||||||
|
break;
|
||||||
case VALUE_TYPE.surface :
|
|
||||||
draw_tooltip_surface(content);
|
case VALUE_TYPE.color :
|
||||||
break;
|
draw_tooltip_color(content);
|
||||||
|
break;
|
||||||
case VALUE_TYPE.rigid :
|
|
||||||
draw_tooltip_text("[" + __txt("Rigidbody Object") + " (id: " + string(content[$ "object"]) + ")]");
|
case VALUE_TYPE.gradient :
|
||||||
break;
|
draw_tooltip_gradient(content);
|
||||||
|
break;
|
||||||
case VALUE_TYPE.particle :
|
|
||||||
var txt = "[" +
|
case VALUE_TYPE.d3object :
|
||||||
__txt("Particle Object") +
|
draw_tooltip_text("[" + __txt("3D Object") + "]");
|
||||||
" (size: " + string(array_length(content)) + ") " +
|
break;
|
||||||
"]";
|
|
||||||
draw_tooltip_text(txt);
|
case VALUE_TYPE.object :
|
||||||
break;
|
draw_tooltip_text("[" + __txt("Object") + "]");
|
||||||
|
break;
|
||||||
case VALUE_TYPE.pathnode :
|
|
||||||
draw_tooltip_text("[" + __txt("Path Object") + "]");
|
case VALUE_TYPE.surface :
|
||||||
break;
|
draw_tooltip_surface(content);
|
||||||
|
break;
|
||||||
case VALUE_TYPE.sdomain :
|
|
||||||
draw_tooltip_text("[" + __txt("Domain") + " (id: " + string(content) + ")]");
|
case VALUE_TYPE.rigid :
|
||||||
break;
|
draw_tooltip_text("[" + __txt("Rigidbody Object") + " (id: " + string(content[$ "object"]) + ")]");
|
||||||
|
break;
|
||||||
case VALUE_TYPE.strands :
|
|
||||||
var txt = __txt("Strands Object");
|
case VALUE_TYPE.particle :
|
||||||
if(is_struct(content))
|
var txt = "[" +
|
||||||
txt += " (strands: " + string(array_length(content.hairs)) + ")";
|
__txt("Particle Object") +
|
||||||
draw_tooltip_text("[" + txt + "]");
|
" (size: " + string(array_length(content)) + ") " +
|
||||||
break;
|
"]";
|
||||||
|
draw_tooltip_text(txt);
|
||||||
case VALUE_TYPE.mesh :
|
break;
|
||||||
var txt = __txt("Mesh Object");
|
|
||||||
if(is_struct(content))
|
case VALUE_TYPE.pathnode :
|
||||||
txt += " (triangles: " + string(array_length(content.triangles)) + ")";
|
draw_tooltip_text("[" + __txt("Path Object") + "]");
|
||||||
draw_tooltip_text("[" + txt + "]");
|
break;
|
||||||
break;
|
|
||||||
|
case VALUE_TYPE.sdomain :
|
||||||
case VALUE_TYPE.d3vertex :
|
draw_tooltip_text("[" + __txt("Domain") + " (id: " + string(content) + ")]");
|
||||||
var txt = __txt("3D Vertex");
|
break;
|
||||||
txt += " (groups: " + string(array_length(content)) + ")";
|
|
||||||
draw_tooltip_text("[" + txt + "]");
|
case VALUE_TYPE.strands :
|
||||||
break;
|
var txt = __txt("Strands Object");
|
||||||
|
if(is_struct(content))
|
||||||
case VALUE_TYPE.buffer :
|
txt += " (strands: " + string(array_length(content.hairs)) + ")";
|
||||||
draw_tooltip_buffer(content);
|
draw_tooltip_text("[" + txt + "]");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "sprite" :
|
case VALUE_TYPE.mesh :
|
||||||
draw_tooltip_sprite(content);
|
var txt = __txt("Mesh Object");
|
||||||
break;
|
if(is_struct(content))
|
||||||
|
txt += " (triangles: " + string(array_length(content.triangles)) + ")";
|
||||||
default :
|
draw_tooltip_text("[" + txt + "]");
|
||||||
var tt = "";
|
break;
|
||||||
if(is_struct(content)) tt = $"[{instanceof(content)}] {content}";
|
|
||||||
else tt = string(content);
|
case VALUE_TYPE.d3vertex :
|
||||||
|
var txt = __txt("3D Vertex");
|
||||||
draw_tooltip_text(tt);
|
txt += " (groups: " + string(array_length(content)) + ")";
|
||||||
}
|
draw_tooltip_text("[" + txt + "]");
|
||||||
} else if(TOOLTIP != "")
|
break;
|
||||||
draw_tooltip_text(TOOLTIP);
|
|
||||||
|
case VALUE_TYPE.buffer :
|
||||||
|
draw_tooltip_buffer(content);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "sprite" :
|
||||||
|
draw_tooltip_sprite(content);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
var tt = "";
|
||||||
|
if(is_struct(content)) tt = $"[{instanceof(content)}] {content}";
|
||||||
|
else tt = string(content);
|
||||||
|
|
||||||
|
draw_tooltip_text(tt);
|
||||||
|
}
|
||||||
|
} else if(TOOLTIP != "")
|
||||||
|
draw_tooltip_text(TOOLTIP);
|
||||||
|
}
|
||||||
TOOLTIP = "";
|
TOOLTIP = "";
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
|
@ -587,7 +587,7 @@ function BBMOD_Quaternion(_x=0.0, _y=0.0, _z=0.0, _w=1.0) constructor
|
||||||
return self;
|
return self;
|
||||||
};
|
};
|
||||||
|
|
||||||
static ToEuler = function() {
|
static ToEuler = function(isArray = false) {
|
||||||
var ysqr = Y * Y;
|
var ysqr = Y * Y;
|
||||||
|
|
||||||
// roll (x-axis rotation)
|
// roll (x-axis rotation)
|
||||||
|
@ -606,11 +606,15 @@ function BBMOD_Quaternion(_x=0.0, _y=0.0, _z=0.0, _w=1.0) constructor
|
||||||
var yaw = arctan2(t3, t4);
|
var yaw = arctan2(t3, t4);
|
||||||
|
|
||||||
// Convert radians to degrees
|
// Convert radians to degrees
|
||||||
var _dx = roll * 180.0 / pi;
|
var _dx = roll * 180.0 / pi;
|
||||||
var _dy = pitch * 180.0 / pi;
|
var _dy = pitch * 180.0 / pi;
|
||||||
var _dz = yaw * 180.0 / pi;
|
var _dz = yaw * 180.0 / pi;
|
||||||
|
|
||||||
return new __rot3(_dx, _dy, _dz);
|
_dx = round(_dx * 1000) / 1000;
|
||||||
|
_dy = round(_dy * 1000) / 1000;
|
||||||
|
_dz = round(_dz * 1000) / 1000;
|
||||||
|
|
||||||
|
return isArray? [ _dx, _dy, _dz ] : new __rot3(_dx, _dy, _dz);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @func ToMatrix([_dest[, _index]])
|
/// @func ToMatrix([_dest[, _index]])
|
||||||
|
|
|
@ -35,7 +35,7 @@ function Node_3D(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constr
|
||||||
static refreshPreview = function() { #region
|
static refreshPreview = function() { #region
|
||||||
var _prev_obj = getPreviewObjects();
|
var _prev_obj = getPreviewObjects();
|
||||||
|
|
||||||
mesh_prev_surface = surface_verify(mesh_prev_surface, 64, 64);
|
mesh_prev_surface = surface_verify(mesh_prev_surface, PREFERENCES.node_3d_preview_size, PREFERENCES.node_3d_preview_size);
|
||||||
surface_set_target(mesh_prev_surface);
|
surface_set_target(mesh_prev_surface);
|
||||||
DRAW_CLEAR
|
DRAW_CLEAR
|
||||||
|
|
||||||
|
@ -56,12 +56,12 @@ function Node_3D(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constr
|
||||||
|
|
||||||
D3D_GLOBAL_PREVIEW.custom_transform.position.set(_c._multiply(-1));
|
D3D_GLOBAL_PREVIEW.custom_transform.position.set(_c._multiply(-1));
|
||||||
|
|
||||||
var _sca = 1 / _b.getMaximumScale();
|
var _sca = 2 / _b.getScale();
|
||||||
D3D_GLOBAL_PREVIEW.custom_transform.scale.set(_sca);
|
//print($"Submitting object {_prev}\n{_b}, {_c}, {_sca}");
|
||||||
|
|
||||||
|
D3D_GLOBAL_PREVIEW.custom_transform.scale.set(_sca);
|
||||||
D3D_GLOBAL_PREVIEW.submitUI(_prev);
|
D3D_GLOBAL_PREVIEW.submitUI(_prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
surface_reset_target();
|
surface_reset_target();
|
||||||
|
|
||||||
D3D_GLOBAL_PREVIEW.camera.resetCamera();
|
D3D_GLOBAL_PREVIEW.camera.resetCamera();
|
||||||
|
@ -78,5 +78,8 @@ function Node_3D(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constr
|
||||||
if(!isHighlightingInGraph()) aa *= 0.25;
|
if(!isHighlightingInGraph()) aa *= 0.25;
|
||||||
|
|
||||||
draw_surface_bbox(mesh_prev_surface, bbox,, aa);
|
draw_surface_bbox(mesh_prev_surface, bbox,, aa);
|
||||||
|
onDrawNodeOver(xx, yy, _mx, _my, _s, _hover, _focus);
|
||||||
} #endregion
|
} #endregion
|
||||||
|
|
||||||
|
static onDrawNodeOver = function(xx, yy, _mx, _my, _s, _hover = false, _focus = false) { }
|
||||||
}
|
}
|
|
@ -49,9 +49,9 @@ function Node_3D_Object(_x, _y, _group = noone) : Node_3D(_x, _y, _group) constr
|
||||||
tools = [ tool_pos, tool_rot, tool_sca ];
|
tools = [ tool_pos, tool_rot, tool_sca ];
|
||||||
|
|
||||||
tool_axis_edit = new scrollBox([ "local", "global" ], function(val) { tool_attribute.context = val; });
|
tool_axis_edit = new scrollBox([ "local", "global" ], function(val) { tool_attribute.context = val; });
|
||||||
tool_axis_edit.font = f_p2;
|
// tool_axis_edit.font = f_p2;
|
||||||
tool_axis_edit.arrow_spr = THEME.arrow;
|
// tool_axis_edit.arrow_spr = THEME.arrow;
|
||||||
tool_axis_edit.arrow_ind = 3;
|
// tool_axis_edit.arrow_ind = 3;
|
||||||
tool_attribute.context = 0;
|
tool_attribute.context = 0;
|
||||||
tool_settings = [
|
tool_settings = [
|
||||||
[ "Axis", tool_axis_edit, "context", tool_attribute ],
|
[ "Axis", tool_axis_edit, "context", tool_attribute ],
|
||||||
|
@ -279,7 +279,7 @@ function Node_3D_Object(_x, _y, _group = noone) : Node_3D(_x, _y, _group) constr
|
||||||
|
|
||||||
static drawGizmoRotation = function(index, object, _vpos, active, params, _mx, _my, _snx, _sny, _panel) { #region
|
static drawGizmoRotation = function(index, object, _vpos, active, params, _mx, _my, _snx, _sny, _panel) { #region
|
||||||
#region ---- main ----
|
#region ---- main ----
|
||||||
var _rot = inputs[| index].getValue(,,, true);
|
var _rot = inputs[| index].getValue();
|
||||||
var _qrot = object == noone? new BBMOD_Quaternion() : object.transform.rotation;
|
var _qrot = object == noone? new BBMOD_Quaternion() : object.transform.rotation;
|
||||||
var _qinv = new BBMOD_Quaternion().FromAxisAngle(new BBMOD_Vec3(1, 0, 0), 90);
|
var _qinv = new BBMOD_Quaternion().FromAxisAngle(new BBMOD_Vec3(1, 0, 0), 90);
|
||||||
|
|
||||||
|
@ -293,7 +293,7 @@ function Node_3D_Object(_x, _y, _group = noone) : Node_3D(_x, _y, _group) constr
|
||||||
var th;
|
var th;
|
||||||
|
|
||||||
var _posView = _camera.worldPointToViewPoint(_vpos);
|
var _posView = _camera.worldPointToViewPoint(_vpos);
|
||||||
|
|
||||||
var cx = _posView.x;
|
var cx = _posView.x;
|
||||||
var cy = _posView.y;
|
var cy = _posView.y;
|
||||||
|
|
||||||
|
|
|
@ -19,4 +19,4 @@ function __bbox3D(first, second) constructor {
|
||||||
abs(first.z - second.z),
|
abs(first.z - second.z),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ function __3dObject() constructor {
|
||||||
vertex = [];
|
vertex = [];
|
||||||
normal_vertex = [];
|
normal_vertex = [];
|
||||||
object_counts = 1;
|
object_counts = 1;
|
||||||
VB = noone;
|
VB = [];
|
||||||
|
|
||||||
NVB = noone;
|
NVB = noone;
|
||||||
normal_draw_size = 0.2;
|
normal_draw_size = 0.2;
|
||||||
|
@ -134,11 +134,9 @@ function __3dObject() constructor {
|
||||||
|
|
||||||
preSubmitVertex(scene);
|
preSubmitVertex(scene);
|
||||||
|
|
||||||
if(VB != noone) { #region
|
transform.submitMatrix();
|
||||||
transform.submitMatrix();
|
|
||||||
|
matrix_set(matrix_world, matrix_stack_top());
|
||||||
matrix_set(matrix_world, matrix_stack_top());
|
|
||||||
} #endregion
|
|
||||||
|
|
||||||
#region ++++ Submit & Material ++++
|
#region ++++ Submit & Material ++++
|
||||||
gpu_set_tex_repeat(true);
|
gpu_set_tex_repeat(true);
|
||||||
|
@ -173,7 +171,7 @@ function __3dObject() constructor {
|
||||||
} else
|
} else
|
||||||
vertex_submit(VB[i], render_type, _tex);
|
vertex_submit(VB[i], render_type, _tex);
|
||||||
|
|
||||||
//print($"Submit vertex ({scene}) [{VB[i]}]");
|
// print($"Submit vertex ({scene}) [{VB[i]}: {vertex_get_buffer_size(VB[i])}]");
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu_set_tex_repeat(false);
|
gpu_set_tex_repeat(false);
|
||||||
|
@ -242,11 +240,9 @@ function __3dObject() constructor {
|
||||||
} #endregion
|
} #endregion
|
||||||
|
|
||||||
static destroy = function() { #region
|
static destroy = function() { #region
|
||||||
if(is_array(VB)) {
|
for( var i = 0, n = array_length(VB); i < n; i++ )
|
||||||
for( var i = 0, n = array_length(VB); i < n; i++ )
|
vertex_delete_buffer(VB[i]);
|
||||||
vertex_delete_buffer(VB[i]);
|
VB = [];
|
||||||
} else if(VB != noone)
|
|
||||||
vertex_delete_buffer(VB);
|
|
||||||
onDestroy();
|
onDestroy();
|
||||||
} #endregion
|
} #endregion
|
||||||
|
|
||||||
|
|
|
@ -32,10 +32,13 @@ function Node_3D_Mesh_Obj(_x, _y, _group = noone) : Node_3D_Mesh(_x, _y, _group)
|
||||||
inputs[| in_mesh + 1] = nodeValue("Flip UV", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true, "Flip UV axis, can be use to fix some texture mapping error.")
|
inputs[| in_mesh + 1] = nodeValue("Flip UV", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true, "Flip UV axis, can be use to fix some texture mapping error.")
|
||||||
.rejectArray();
|
.rejectArray();
|
||||||
|
|
||||||
|
inputs[| in_mesh + 2] = nodeValue("Import Scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1)
|
||||||
|
.rejectArray();
|
||||||
|
|
||||||
input_display_list = [
|
input_display_list = [
|
||||||
__d3d_input_list_mesh,
|
__d3d_input_list_mesh,
|
||||||
__d3d_input_list_transform,
|
__d3d_input_list_transform,
|
||||||
["Object", false], in_mesh + 0,
|
["Object", false], in_mesh + 0, in_mesh + 2,
|
||||||
["Material", false], in_mesh + 1,
|
["Material", false], in_mesh + 1,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -57,7 +60,10 @@ function Node_3D_Mesh_Obj(_x, _y, _group = noone) : Node_3D_Mesh(_x, _y, _group)
|
||||||
insp1UpdateTooltip = __txt("Refresh");
|
insp1UpdateTooltip = __txt("Refresh");
|
||||||
insp1UpdateIcon = [ THEME.refresh_icon, 1, COLORS._main_value_positive ];
|
insp1UpdateIcon = [ THEME.refresh_icon, 1, COLORS._main_value_positive ];
|
||||||
|
|
||||||
static onInspector1Update = function() { current_path = ""; }
|
static onInspector1Update = function() {
|
||||||
|
current_path = "";
|
||||||
|
outputs[| 0].setValue(noone);
|
||||||
|
}
|
||||||
|
|
||||||
function setPath(path) { inputs[| in_mesh + 0].setValue(path); }
|
function setPath(path) { inputs[| in_mesh + 0].setValue(path); }
|
||||||
|
|
||||||
|
@ -100,7 +106,9 @@ function Node_3D_Mesh_Obj(_x, _y, _group = noone) : Node_3D_Mesh(_x, _y, _group)
|
||||||
if(!file_exists_empty(_path)) return;
|
if(!file_exists_empty(_path)) return;
|
||||||
current_path = _path;
|
current_path = _path;
|
||||||
|
|
||||||
readObj_init();
|
var _scale = inputs[| in_mesh + 2].getValue();
|
||||||
|
|
||||||
|
readObj_init(_scale);
|
||||||
|
|
||||||
obj_read_time = get_timer();
|
obj_read_time = get_timer();
|
||||||
obj_read_file = file_text_open_read(current_path);
|
obj_read_file = file_text_open_read(current_path);
|
||||||
|
@ -119,23 +127,24 @@ function Node_3D_Mesh_Obj(_x, _y, _group = noone) : Node_3D_Mesh(_x, _y, _group)
|
||||||
use_display_list = true;
|
use_display_list = true;
|
||||||
if(obj_raw == noone) return;
|
if(obj_raw == noone) return;
|
||||||
|
|
||||||
//var txt = $"========== OBJ import ==========\n";
|
// var txt = $"========== OBJ import ==========\n";
|
||||||
//txt += $"Vertex counts: {obj_raw.vertex_count}\n";
|
// txt += $"Vertex counts: {obj_raw.vertex_count}\n";
|
||||||
//txt += $"Object counts: {obj_raw.object_counts}\n";
|
// txt += $"Object counts: {obj_raw.object_counts}\n";
|
||||||
//txt += $"Material counts: {array_length(obj_raw.materials)}\n";
|
// txt += $"Material counts: {array_length(obj_raw.materials)}\n";
|
||||||
//txt += $"Model BBOX: {obj_raw.model_size}\n";
|
// txt += $"Model BBOX: {obj_raw.model_size}\n";
|
||||||
//txt += $"Load completed in {(get_timer() - obj_read_time) / 1000} ms\n";
|
// txt += $"Load completed in {(get_timer() - obj_read_time) / 1000} ms\n";
|
||||||
//print(txt);
|
// print(txt);
|
||||||
|
|
||||||
var span = max(abs(obj_raw.model_size.x), abs(obj_raw.model_size.y), abs(obj_raw.model_size.z));
|
var span = max(abs(obj_raw.model_size.x), abs(obj_raw.model_size.y), abs(obj_raw.model_size.z));
|
||||||
if(span > 10) noti_warning($"The model is tool large to display properly ({span}u). Scale the model down to preview.");
|
if(span > 10) noti_warning($"The model is tool large to display properly ({span}u). Scale the model down to preview.");
|
||||||
|
|
||||||
if(object != noone) object.destroy();
|
if(object != noone) object.destroy();
|
||||||
|
|
||||||
object = new __3dObject();
|
object = new __3dObject();
|
||||||
object.VB = obj_raw.vertex_groups;
|
object.VB = obj_raw.vertex_groups;
|
||||||
object.vertex = obj_raw.vertex;
|
object.vertex = obj_raw.vertex;
|
||||||
object.object_counts = obj_raw.object_counts;
|
|
||||||
object.size = obj_raw.model_size;
|
object.size = obj_raw.model_size;
|
||||||
|
object.object_counts = obj_raw.object_counts;
|
||||||
use_normal = obj_raw.use_normal;
|
use_normal = obj_raw.use_normal;
|
||||||
|
|
||||||
materialNames = [ "Material" ];
|
materialNames = [ "Material" ];
|
||||||
|
@ -171,6 +180,8 @@ function Node_3D_Mesh_Obj(_x, _y, _group = noone) : Node_3D_Mesh(_x, _y, _group)
|
||||||
for(var i = 0; i < array_length(materialNames); i++)
|
for(var i = 0; i < array_length(materialNames); i++)
|
||||||
createMaterial(i);
|
createMaterial(i);
|
||||||
|
|
||||||
|
outputs[| 0].setValue(object);
|
||||||
|
|
||||||
triggerRender();
|
triggerRender();
|
||||||
} #endregion
|
} #endregion
|
||||||
|
|
||||||
|
@ -206,6 +217,7 @@ function Node_3D_Mesh_Obj(_x, _y, _group = noone) : Node_3D_Mesh(_x, _y, _group)
|
||||||
_object.VB = object.VB;
|
_object.VB = object.VB;
|
||||||
_object.NVB = object.NVB;
|
_object.NVB = object.NVB;
|
||||||
_object.vertex = object.vertex;
|
_object.vertex = object.vertex;
|
||||||
|
_object.size = object.size;
|
||||||
_object.object_counts = object.object_counts;
|
_object.object_counts = object.object_counts;
|
||||||
_object.materials = materials;
|
_object.materials = materials;
|
||||||
_object.material_index = materialIndex;
|
_object.material_index = materialIndex;
|
||||||
|
@ -217,7 +229,7 @@ function Node_3D_Mesh_Obj(_x, _y, _group = noone) : Node_3D_Mesh(_x, _y, _group)
|
||||||
|
|
||||||
static getPreviewValues = function() { return array_safe_get_fast(all_inputs, in_mesh + 2, noone); }
|
static getPreviewValues = function() { return array_safe_get_fast(all_inputs, in_mesh + 2, noone); }
|
||||||
|
|
||||||
static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) { #region
|
static onDrawNodeOver = function(xx, yy, _mx, _my, _s, _hover, _focus) { #region
|
||||||
if(!obj_reading) return;
|
if(!obj_reading) return;
|
||||||
|
|
||||||
var cx = xx + w * _s / 2;
|
var cx = xx + w * _s / 2;
|
||||||
|
@ -225,7 +237,6 @@ function Node_3D_Mesh_Obj(_x, _y, _group = noone) : Node_3D_Mesh(_x, _y, _group)
|
||||||
var rr = min(w - 32, h - 32) * _s / 2;
|
var rr = min(w - 32, h - 32) * _s / 2;
|
||||||
|
|
||||||
draw_set_color(COLORS._main_icon);
|
draw_set_color(COLORS._main_icon);
|
||||||
//draw_arc(cx, cy, rr, 90, 90 - 360 * (obj_read_progress + obj_read_prog_sub) / obj_read_prog_tot, 4 * _s, 180);
|
|
||||||
draw_arc(cx, cy, rr, current_time / 5, current_time / 5 + 90, 4 * _s, 90);
|
draw_arc(cx, cy, rr, current_time / 5, current_time / 5 + 90, 4 * _s, 90);
|
||||||
} #endregion
|
} #endregion
|
||||||
}
|
}
|
|
@ -302,7 +302,7 @@ function Node_Export(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
|
||||||
} #endregion
|
} #endregion
|
||||||
|
|
||||||
static renderWebp = function(temp_path, target_path) { #region
|
static renderWebp = function(temp_path, target_path) { #region
|
||||||
var _path = file_find_first(temp_path + "*.png", 0);
|
var _path = file_find_first(temp_path + "*.png", 0);
|
||||||
var frames = [];
|
var frames = [];
|
||||||
|
|
||||||
while(_path != "") {
|
while(_path != "") {
|
||||||
|
@ -311,7 +311,7 @@ function Node_Export(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
|
||||||
var shell_cmd = _pathTemp + " -define webp:lossless=true " + _frame;
|
var shell_cmd = _pathTemp + " -define webp:lossless=true " + _frame;
|
||||||
|
|
||||||
array_push(frames, _frame);
|
array_push(frames, _frame);
|
||||||
shell_execute_async(magick, shell_cmd, self);
|
shell_execute_async(magick, shell_cmd, self, false);
|
||||||
|
|
||||||
_path = file_find_next();
|
_path = file_find_next();
|
||||||
}
|
}
|
||||||
|
@ -323,7 +323,7 @@ function Node_Export(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
|
||||||
var cmd = "";
|
var cmd = "";
|
||||||
|
|
||||||
for( var i = 0, n = array_length(frames); i < n; i++ )
|
for( var i = 0, n = array_length(frames); i < n; i++ )
|
||||||
cmd += "-frame " + frames[i] + " +" + string(framerate) + "+0+0+1 ";
|
cmd += $"-frame {frames[i]} +{framerate}+0+0+1 ";
|
||||||
|
|
||||||
cmd += "-bgcolor 0,0,0,0 ";
|
cmd += "-bgcolor 0,0,0,0 ";
|
||||||
cmd += "-o " + string_quote(target_path);
|
cmd += "-o " + string_quote(target_path);
|
||||||
|
@ -341,7 +341,9 @@ function Node_Export(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
|
||||||
var qual = getInputData(10);
|
var qual = getInputData(10);
|
||||||
if(rate == 0) rate = 1;
|
if(rate == 0) rate = 1;
|
||||||
|
|
||||||
|
temp_path = string_replace_all(temp_path, "/", "\\");
|
||||||
target_path = string_replace_all(target_path, "/", "\\");
|
target_path = string_replace_all(target_path, "/", "\\");
|
||||||
|
|
||||||
var framerate = 100 / rate;
|
var framerate = 100 / rate;
|
||||||
var loop_str = loop? 0 : 1;
|
var loop_str = loop? 0 : 1;
|
||||||
var use_gifski = false;
|
var use_gifski = false;
|
||||||
|
|
|
@ -13,7 +13,7 @@ function Node_Grid(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons
|
||||||
.setMappable(13);
|
.setMappable(13);
|
||||||
|
|
||||||
inputs[| 3] = nodeValue("Gap", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1)
|
inputs[| 3] = nodeValue("Gap", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1)
|
||||||
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 0.5, 0.01] })
|
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 0.5, 0.001] })
|
||||||
.setMappable(14);
|
.setMappable(14);
|
||||||
|
|
||||||
inputs[| 4] = nodeValue("Angle", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0)
|
inputs[| 4] = nodeValue("Angle", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0)
|
||||||
|
|
|
@ -17,7 +17,7 @@ function Node_Grid_Hex(_x, _y, _group = noone) : Node_Processor(_x, _y, _group)
|
||||||
.setMappable(12);
|
.setMappable(12);
|
||||||
|
|
||||||
inputs[| 4] = nodeValue("Gap", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1)
|
inputs[| 4] = nodeValue("Gap", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1)
|
||||||
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 0.5, 0.01] })
|
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 0.5, 0.001] })
|
||||||
.setMappable(13);
|
.setMappable(13);
|
||||||
|
|
||||||
inputs[| 5] = nodeValue("Tile color", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white) )
|
inputs[| 5] = nodeValue("Tile color", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white) )
|
||||||
|
|
|
@ -13,7 +13,7 @@ function Node_Grid_Tri(_x, _y, _group = noone) : Node_Processor(_x, _y, _group)
|
||||||
.setMappable(11);
|
.setMappable(11);
|
||||||
|
|
||||||
inputs[| 3] = nodeValue("Gap", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1)
|
inputs[| 3] = nodeValue("Gap", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1)
|
||||||
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 0.5, 0.01] })
|
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 0.5, 0.001] })
|
||||||
.setMappable(12);
|
.setMappable(12);
|
||||||
|
|
||||||
inputs[| 4] = nodeValue("Angle", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0)
|
inputs[| 4] = nodeValue("Angle", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0)
|
||||||
|
|
|
@ -17,7 +17,7 @@ function Node_Herringbone_Tile(_x, _y, _group = noone) : Node_Processor(_x, _y,
|
||||||
.setMappable(12);
|
.setMappable(12);
|
||||||
|
|
||||||
inputs[| 4] = nodeValue("Gap", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.25)
|
inputs[| 4] = nodeValue("Gap", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.25)
|
||||||
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 0.5, 0.01] })
|
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 0.5, 0.001] })
|
||||||
.setMappable(13);
|
.setMappable(13);
|
||||||
|
|
||||||
inputs[| 5] = nodeValue("Tile color", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white) )
|
inputs[| 5] = nodeValue("Tile color", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white) )
|
||||||
|
|
|
@ -17,7 +17,7 @@ function Node_Pytagorean_Tile(_x, _y, _group = noone) : Node_Processor(_x, _y, _
|
||||||
.setMappable(12);
|
.setMappable(12);
|
||||||
|
|
||||||
inputs[| 4] = nodeValue("Gap", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.25)
|
inputs[| 4] = nodeValue("Gap", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.25)
|
||||||
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 0.5, 0.01] })
|
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 0.5, 0.001] })
|
||||||
.setMappable(13);
|
.setMappable(13);
|
||||||
|
|
||||||
inputs[| 5] = nodeValue("Tile color", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white) )
|
inputs[| 5] = nodeValue("Tile color", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white) )
|
||||||
|
|
|
@ -17,7 +17,7 @@ function Node_Random_Tile(_x, _y, _group = noone) : Node_Processor(_x, _y, _grou
|
||||||
.setMappable(12);
|
.setMappable(12);
|
||||||
|
|
||||||
inputs[| 4] = nodeValue("Gap", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1)
|
inputs[| 4] = nodeValue("Gap", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1)
|
||||||
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 0.5, 0.01] })
|
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 0.5, 0.001] })
|
||||||
.setMappable(13);
|
.setMappable(13);
|
||||||
|
|
||||||
inputs[| 5] = nodeValue("Tile color", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white) )
|
inputs[| 5] = nodeValue("Tile color", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white) )
|
||||||
|
|
|
@ -59,7 +59,7 @@ function Node_Shadow_Cast(_x, _y, _group = noone) : Node_Processor(_x, _y, _grou
|
||||||
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 16, 0.1] });
|
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 16, 0.1] });
|
||||||
|
|
||||||
inputs[| 16] = nodeValue("Ambient occlusion strength", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1)
|
inputs[| 16] = nodeValue("Ambient occlusion strength", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1)
|
||||||
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 0.5, 0.01] });
|
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 0.5, 0.001] });
|
||||||
|
|
||||||
inputs[| 17] = nodeValue("Active", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true);
|
inputs[| 17] = nodeValue("Active", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true);
|
||||||
active_index = 17;
|
active_index = 17;
|
||||||
|
|
|
@ -64,7 +64,7 @@ function Node_Shape(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) con
|
||||||
.setDisplay(VALUE_DISPLAY.rotation_range);
|
.setDisplay(VALUE_DISPLAY.rotation_range);
|
||||||
|
|
||||||
inputs[| 9] = nodeValue("Corner radius", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0)
|
inputs[| 9] = nodeValue("Corner radius", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0)
|
||||||
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 0.5, 0.01] });
|
.setDisplay(VALUE_DISPLAY.slider, { range: [0, 0.5, 0.001] });
|
||||||
|
|
||||||
inputs[| 10] = nodeValue("Shape color", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, c_white);
|
inputs[| 10] = nodeValue("Shape color", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, c_white);
|
||||||
|
|
||||||
|
|
|
@ -1151,7 +1151,7 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
|
||||||
});
|
});
|
||||||
|
|
||||||
extract_node = "Node_Vector4";
|
extract_node = "Node_Vector4";
|
||||||
display_data.angle_display = QUARTERNION_DISPLAY.quarterion;
|
display_data.angle_display = QUARTERNION_DISPLAY.euler;
|
||||||
break; #endregion
|
break; #endregion
|
||||||
|
|
||||||
case VALUE_DISPLAY.path_anchor : #region
|
case VALUE_DISPLAY.path_anchor : #region
|
||||||
|
@ -1551,19 +1551,6 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
|
||||||
return applyUnit? unit.apply(value, arrIndex) : value;
|
return applyUnit? unit.apply(value, arrIndex) : value;
|
||||||
} #endregion
|
} #endregion
|
||||||
|
|
||||||
if(display_type == VALUE_DISPLAY.d3quarternion) { #region
|
|
||||||
if(!applyUnit) return value;
|
|
||||||
var dispType = display_data.angle_display;
|
|
||||||
|
|
||||||
switch(dispType) {
|
|
||||||
case QUARTERNION_DISPLAY.quarterion :
|
|
||||||
return value;
|
|
||||||
case QUARTERNION_DISPLAY.euler :
|
|
||||||
var euler = new BBMOD_Quaternion().FromEuler(value[0], value[1], value[2]).ToArray();
|
|
||||||
return euler;
|
|
||||||
}
|
|
||||||
} #endregion
|
|
||||||
|
|
||||||
if(type == VALUE_TYPE.text) { #region
|
if(type == VALUE_TYPE.text) { #region
|
||||||
switch(display_type) {
|
switch(display_type) {
|
||||||
case VALUE_DISPLAY.text_array : return value;
|
case VALUE_DISPLAY.text_array : return value;
|
||||||
|
@ -1910,6 +1897,13 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
|
||||||
} else
|
} else
|
||||||
val = ds_list_empty(animator.values)? 0 : animator.processType(animator.values[| 0].value);
|
val = ds_list_empty(animator.values)? 0 : animator.processType(animator.values[| 0].value);
|
||||||
|
|
||||||
|
if(display_type == VALUE_DISPLAY.d3quarternion) {
|
||||||
|
switch(display_data.angle_display) {
|
||||||
|
case QUARTERNION_DISPLAY.quarterion : return val;
|
||||||
|
case QUARTERNION_DISPLAY.euler : return new BBMOD_Quaternion(val[0], val[1], val[2], val[3]).ToEuler(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
} #endregion
|
} #endregion
|
||||||
|
|
||||||
|
@ -1992,6 +1986,7 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
|
||||||
|
|
||||||
static setValueInspector = function(val = 0, index = noone) { #region
|
static setValueInspector = function(val = 0, index = noone) { #region
|
||||||
INLINE
|
INLINE
|
||||||
|
|
||||||
var res = false;
|
var res = false;
|
||||||
val = unit.invApply(val);
|
val = unit.invApply(val);
|
||||||
|
|
||||||
|
@ -2002,27 +1997,32 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
|
||||||
var _node = PANEL_INSPECTOR.inspectings[i];
|
var _node = PANEL_INSPECTOR.inspectings[i];
|
||||||
if(ind >= ds_list_size(_node.inputs)) continue;
|
if(ind >= ds_list_size(_node.inputs)) continue;
|
||||||
|
|
||||||
var r = _node.inputs[| ind].setValueDirect(val, index);
|
var r = _node.inputs[| ind].setValueInspectorDirect(val, index);
|
||||||
if(_node == node) res = r;
|
if(_node == node) res = r;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
res = setValueDirect(val, index);
|
res = setValueInspectorDirect(val, index);
|
||||||
|
|
||||||
//print($"Node {node} : {node.name} {node.internalName}");
|
|
||||||
//print($"Inspecting {PANEL_INSPECTOR.inspecting} : {PANEL_INSPECTOR.inspecting.name} {PANEL_INSPECTOR.inspecting.internalName}");
|
|
||||||
//print($"{node == PANEL_INSPECTOR.inspecting}");
|
|
||||||
//print("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
} #endregion
|
} #endregion
|
||||||
|
|
||||||
|
static setValueInspectorDirect = function(val = 0, index = noone) {
|
||||||
|
if(display_type == VALUE_DISPLAY.d3quarternion && display_data.angle_display == QUARTERNION_DISPLAY.euler) {
|
||||||
|
var _qval = new BBMOD_Quaternion().FromEuler(-val[0], -val[1], -val[2]).ToArray();
|
||||||
|
var _eval = new BBMOD_Quaternion(_qval[0], _qval[1], _qval[2], _qval[3]).ToEuler(true);
|
||||||
|
return setValueDirect(_qval);
|
||||||
|
}
|
||||||
|
|
||||||
|
return setValueDirect(val, index);
|
||||||
|
}
|
||||||
|
|
||||||
static setValueDirect = function(val = 0, index = noone, record = true, time = CURRENT_FRAME, _update = true) { #region
|
static setValueDirect = function(val = 0, index = noone, record = true, time = CURRENT_FRAME, _update = true) { #region
|
||||||
is_modified = true;
|
is_modified = true;
|
||||||
var updated = false;
|
var updated = false;
|
||||||
var _val = val;
|
var _val = val;
|
||||||
var _inp = connect_type == JUNCTION_CONNECT.input;
|
var _inp = connect_type == JUNCTION_CONNECT.input;
|
||||||
|
|
||||||
if(sep_axis) {
|
if(sep_axis) {
|
||||||
if(index == noone) {
|
if(index == noone) {
|
||||||
for( var i = 0, n = array_length(animators); i < n; i++ )
|
for( var i = 0, n = array_length(animators); i < n; i++ )
|
||||||
|
@ -2038,8 +2038,7 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
|
||||||
_val[index] = val;
|
_val[index] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
updated = animator.setValue(_val, _inp && record, time);
|
updated = animator.setValue(_val, _inp && record, time);
|
||||||
//print($"{updated}: {index} - {_val}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type == VALUE_TYPE.gradient) updated = true;
|
if(type == VALUE_TYPE.gradient) updated = true;
|
||||||
|
|
|
@ -1,18 +1,22 @@
|
||||||
function readObj_init() {
|
function readObj_init(_scale = 1) {
|
||||||
obj_reading = true;
|
obj_reading = true;
|
||||||
obj_read_progress = 0;
|
obj_read_progress = 0;
|
||||||
obj_read_prog_sub = 0;
|
obj_read_prog_sub = 0;
|
||||||
obj_read_prog_tot = 3;
|
obj_read_prog_tot = 3;
|
||||||
obj_raw = noone;
|
obj_raw = noone;
|
||||||
|
|
||||||
|
obj_reading_scale = _scale;
|
||||||
|
|
||||||
_VB = [];
|
_VB = [];
|
||||||
_VBT = [];
|
_VBT = [];
|
||||||
_VBN = [];
|
_VBN = [];
|
||||||
mats = [];
|
mats = [];
|
||||||
|
|
||||||
matIndex = [];
|
matIndex = [];
|
||||||
tris = [];
|
tris = [];
|
||||||
mtlPath = "";
|
mtlPath = "";
|
||||||
use_normal = true;
|
use_normal = true;
|
||||||
|
|
||||||
v = ds_list_create();
|
v = ds_list_create();
|
||||||
vt = ds_list_create();
|
vt = ds_list_create();
|
||||||
vn = ds_list_create();
|
vn = ds_list_create();
|
||||||
|
@ -34,7 +38,11 @@ function readObj_file() {
|
||||||
|
|
||||||
switch(sep[0]) {
|
switch(sep[0]) {
|
||||||
case "v" :
|
case "v" :
|
||||||
ds_list_add(v, [ toNumber(sep[1]), toNumber(sep[2]), toNumber(sep[3]) ]);
|
ds_list_add(v, [
|
||||||
|
toNumber(sep[1]) * obj_reading_scale,
|
||||||
|
toNumber(sep[2]) * obj_reading_scale,
|
||||||
|
toNumber(sep[3]) * obj_reading_scale
|
||||||
|
]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "vt" :
|
case "vt" :
|
||||||
|
@ -43,15 +51,11 @@ function readObj_file() {
|
||||||
|
|
||||||
ds_list_add(vt, [ _u, _v ]);
|
ds_list_add(vt, [ _u, _v ]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "vn" :
|
case "vn" :
|
||||||
var _nx = toNumber(sep[1]);
|
var _nx = toNumber(sep[1]);
|
||||||
var _ny = toNumber(sep[2]);
|
var _ny = toNumber(sep[2]);
|
||||||
var _nz = toNumber(sep[3]);
|
var _nz = toNumber(sep[3]);
|
||||||
//var _di = sqrt(_nx * _nx + _ny * _ny + _nz * _nz);
|
|
||||||
|
|
||||||
//_nx /= _di;
|
|
||||||
//_ny /= _di;
|
|
||||||
//_nz /= _di;
|
|
||||||
|
|
||||||
ds_list_add(vn, [ _nx, _ny, _nz ]);
|
ds_list_add(vn, [ _nx, _ny, _nz ]);
|
||||||
break;
|
break;
|
||||||
|
@ -143,23 +147,28 @@ function readObj_cent() {
|
||||||
_bmin = v[| 0];
|
_bmin = v[| 0];
|
||||||
_bmax = v[| 0];
|
_bmax = v[| 0];
|
||||||
cv = [0, 0, 0];
|
cv = [0, 0, 0];
|
||||||
|
|
||||||
vertex = ds_list_size(v);
|
vertex = ds_list_size(v);
|
||||||
|
|
||||||
for( var i = 0; i < vertex; i++ ) {
|
for( var i = 0; i < vertex; i++ ) {
|
||||||
var _v = v[| i];
|
var _v = v[| i];
|
||||||
cv[0] += _v[0];
|
var _v0 = _v[0];
|
||||||
cv[1] += _v[1];
|
var _v1 = _v[1];
|
||||||
cv[2] += _v[2];
|
var _v2 = _v[2];
|
||||||
|
|
||||||
|
cv[0] += _v0;
|
||||||
|
cv[1] += _v1;
|
||||||
|
cv[2] += _v2;
|
||||||
|
|
||||||
_bmin = [
|
_bmin = [
|
||||||
min(_bmin[0], _v[0]),
|
min(_bmin[0], _v0),
|
||||||
min(_bmin[1], _v[1]),
|
min(_bmin[1], _v1),
|
||||||
min(_bmin[2], _v[2]),
|
min(_bmin[2], _v2),
|
||||||
];
|
];
|
||||||
_bmax = [
|
_bmax = [
|
||||||
max(_bmax[0], _v[0]),
|
max(_bmax[0], _v0),
|
||||||
max(_bmax[1], _v[1]),
|
max(_bmax[1], _v1),
|
||||||
max(_bmax[2], _v[2]),
|
max(_bmax[2], _v2),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +182,9 @@ function readObj_cent() {
|
||||||
_bmax[2] - _bmin[2],
|
_bmax[2] - _bmin[2],
|
||||||
);
|
);
|
||||||
|
|
||||||
var sc = 1;
|
//print($"{obj_size}");
|
||||||
|
|
||||||
|
var sc = 1;
|
||||||
//var span = max(abs(_size.x), abs(_size.y), abs(_size.z));
|
//var span = max(abs(_size.x), abs(_size.y), abs(_size.z));
|
||||||
//if(span > 10) sc = span / 10;
|
//if(span > 10) sc = span / 10;
|
||||||
|
|
||||||
|
|
|
@ -166,7 +166,7 @@ function Panel_Graph(project = PROJECT) : PanelContent() constructor {
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ---- position ----
|
#region ---- position ----
|
||||||
scale = [ 0.01, 0.02, 0.05, 0.10, 0.15, 0.20, 0.25, 0.33, 0.50, 0.65, 0.80, 1, 1.2, 1.35, 1.5, 2.0];
|
scale = [ 0.01, 0.02, 0.05, 0.10, 0.15, 0.20, 0.25, 0.33, 0.50, 0.65, 0.80, 1, 1.2, 1.35, 1.5, 2.0 ];
|
||||||
graph_s = 1;
|
graph_s = 1;
|
||||||
graph_s_to = graph_s;
|
graph_s_to = graph_s;
|
||||||
|
|
||||||
|
|
|
@ -926,7 +926,7 @@ function Panel_Preview() : PanelContent() constructor {
|
||||||
|
|
||||||
#region defer
|
#region defer
|
||||||
var _prev_obj = _prev_node.getPreviewObject();
|
var _prev_obj = _prev_node.getPreviewObject();
|
||||||
d3_deferData = d3_scene_preview.deferPass(_prev_obj, w, h, d3_deferData);
|
if(_prev_obj) d3_deferData = d3_scene_preview.deferPass(_prev_obj, w, h, d3_deferData);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region grid
|
#region grid
|
||||||
|
@ -1503,6 +1503,7 @@ function Panel_Preview() : PanelContent() constructor {
|
||||||
}
|
}
|
||||||
|
|
||||||
wdg.setFocusHover(pFOCUS, pHOVER);
|
wdg.setFocusHover(pFOCUS, pHOVER);
|
||||||
|
var _tool_font = f_p3;
|
||||||
|
|
||||||
switch(instanceof(wdg)) {
|
switch(instanceof(wdg)) {
|
||||||
case "textBox" :
|
case "textBox" :
|
||||||
|
@ -1511,16 +1512,27 @@ function Panel_Preview() : PanelContent() constructor {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "buttonGroup":
|
case "buttonGroup":
|
||||||
case "checkBoxGroup" : tolw = tolh * wdg.size; break;
|
case "checkBoxGroup" :
|
||||||
|
tolw = tolh * wdg.size;
|
||||||
|
break;
|
||||||
|
|
||||||
case "checkBox" : tolw = tolh; break;
|
case "checkBox" :
|
||||||
case "scrollBox" : tolw = ui(96); break;
|
tolw = tolh;
|
||||||
case "buttonClass" : tolw = wdg.text == ""? tolh : tolw; break;
|
break;
|
||||||
|
|
||||||
|
case "scrollBox" :
|
||||||
|
tolw = ui(96);
|
||||||
|
_tool_font = f_p2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "buttonClass" :
|
||||||
|
tolw = wdg.text == ""? tolh : tolw;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var params = new widgetParam(tolx, toly, tolw, tolh, atr[$ key],, [ mx, my ])
|
var params = new widgetParam(tolx, toly, tolw, tolh, atr[$ key],, [ mx, my ])
|
||||||
params.s = tolh;
|
params.s = tolh;
|
||||||
params.font = f_p3;
|
params.font = _tool_font;
|
||||||
|
|
||||||
wdg.drawParam(params);
|
wdg.drawParam(params);
|
||||||
|
|
||||||
|
|
|
@ -113,6 +113,7 @@
|
||||||
|
|
||||||
PREFERENCES.node_param_show = false;
|
PREFERENCES.node_param_show = false;
|
||||||
PREFERENCES.node_param_width = 192;
|
PREFERENCES.node_param_width = 192;
|
||||||
|
PREFERENCES.node_3d_preview_size = 256;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
|
@ -4,15 +4,27 @@ enum QUARTERNION_DISPLAY {
|
||||||
}
|
}
|
||||||
|
|
||||||
function quarternionBox(_onModify) : widget() constructor {
|
function quarternionBox(_onModify) : widget() constructor {
|
||||||
onModify = _onModify;
|
onModify = _onModify;
|
||||||
current_value = [];
|
current_value = [ 0, 0, 0, 0 ];
|
||||||
|
current_unit = QUARTERNION_DISPLAY.quarterion;
|
||||||
|
|
||||||
onModifyIndex = function(index, val) {
|
onModifyIndex = function(index, val) {
|
||||||
var v = toNumber(val);
|
var v = toNumber(val);
|
||||||
|
|
||||||
if(is_callable(onModify))
|
if(current_unit == QUARTERNION_DISPLAY.quarterion) {
|
||||||
return onModify(index, v);
|
return onModify(index, v);
|
||||||
return noone;
|
|
||||||
|
} else {
|
||||||
|
var v = toNumber(val);
|
||||||
|
var qv = [
|
||||||
|
current_value[0],
|
||||||
|
current_value[1],
|
||||||
|
current_value[2],
|
||||||
|
];
|
||||||
|
|
||||||
|
qv[index] = v;
|
||||||
|
return onModify(noone, qv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size = 4;
|
size = 4;
|
||||||
|
@ -79,8 +91,6 @@ function quarternionBox(_onModify) : widget() constructor {
|
||||||
if(array_empty(_data)) return 0;
|
if(array_empty(_data)) return 0;
|
||||||
if(is_array(_data[0])) return 0;
|
if(is_array(_data[0])) return 0;
|
||||||
|
|
||||||
current_value = _data;
|
|
||||||
|
|
||||||
var _bs = min(_h, ui(32));
|
var _bs = min(_h, ui(32));
|
||||||
var _disp = struct_try_get(_display_data, "angle_display");
|
var _disp = struct_try_get(_display_data, "angle_display");
|
||||||
|
|
||||||
|
@ -88,7 +98,7 @@ function quarternionBox(_onModify) : widget() constructor {
|
||||||
var bx = _x + _w - _bs;
|
var bx = _x + _w - _bs;
|
||||||
var by = _y + _h / 2 - _bs / 2;
|
var by = _y + _h / 2 - _bs / 2;
|
||||||
tooltip.index = _disp;
|
tooltip.index = _disp;
|
||||||
|
|
||||||
if(buttonInstant(THEME.button_hide, bx, by, _bs, _bs, _m, iactive, ihover, tooltip, THEME.unit_angle, _disp, c_white) == 2) {
|
if(buttonInstant(THEME.button_hide, bx, by, _bs, _bs, _m, iactive, ihover, tooltip, THEME.unit_angle, _disp, c_white) == 2) {
|
||||||
clickable = false;
|
clickable = false;
|
||||||
_display_data.angle_display = (_disp + 1) % 2;
|
_display_data.angle_display = (_disp + 1) % 2;
|
||||||
|
@ -96,6 +106,17 @@ function quarternionBox(_onModify) : widget() constructor {
|
||||||
_w -= _bs + ui(8);
|
_w -= _bs + ui(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
current_unit = _display_data.angle_display;
|
||||||
|
|
||||||
|
if(current_unit == QUARTERNION_DISPLAY.quarterion || (!tb[0].sliding && !tb[1].sliding && !tb[2].sliding)) {
|
||||||
|
current_value[0] = _data[0];
|
||||||
|
current_value[1] = _data[1];
|
||||||
|
current_value[2] = _data[2];
|
||||||
|
|
||||||
|
if(current_unit == QUARTERNION_DISPLAY.quarterion)
|
||||||
|
current_value[3] = _data[3];
|
||||||
|
}
|
||||||
|
|
||||||
size = _disp? 3 : 4;
|
size = _disp? 3 : 4;
|
||||||
var ww = _w / size;
|
var ww = _w / size;
|
||||||
var bx = _x;
|
var bx = _x;
|
||||||
|
@ -124,7 +145,6 @@ function quarternionBox(_onModify) : widget() constructor {
|
||||||
|
|
||||||
static clone = function() { #region
|
static clone = function() { #region
|
||||||
var cln = new quarternionBox(onModify);
|
var cln = new quarternionBox(onModify);
|
||||||
|
|
||||||
return cln;
|
return cln;
|
||||||
} #endregion
|
} #endregion
|
||||||
}
|
}
|
|
@ -24,7 +24,7 @@ function shell_execute(path, command, ref = noone) { #region
|
||||||
return res;
|
return res;
|
||||||
} #endregion
|
} #endregion
|
||||||
|
|
||||||
function shell_execute_async(path, command, ref = noone) { #region
|
function shell_execute_async(path, command, ref = noone, _log = true) { #region
|
||||||
INLINE
|
INLINE
|
||||||
|
|
||||||
if(IS_CMD) return shell_execute(path, command, ref);
|
if(IS_CMD) return shell_execute(path, command, ref);
|
||||||
|
@ -36,7 +36,7 @@ function shell_execute_async(path, command, ref = noone) { #region
|
||||||
|
|
||||||
var txt = $"{path} {command}";
|
var txt = $"{path} {command}";
|
||||||
var res = ProcessExecuteAsync(txt);
|
var res = ProcessExecuteAsync(txt);
|
||||||
print($"Execute async {path} {command} | {res}");
|
if(_log) print($"Execute async {path} {command} | {res}");
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
} #endregion
|
} #endregion
|
||||||
|
|
|
@ -65,12 +65,5 @@ function filename_name_only(name) { #region
|
||||||
return string_replace(name, filename_ext(name), "")
|
return string_replace(name, filename_ext(name), "")
|
||||||
} #endregion
|
} #endregion
|
||||||
|
|
||||||
function string_to_var(str) { #region
|
function string_to_var(str) { INLINE return string_replace_all(string_lower(str), " ", "_"); }
|
||||||
INLINE
|
function string_quote(str) { INLINE return $"\"{str}\""; }
|
||||||
return string_replace_all(string_lower(str), " ", "_");
|
|
||||||
} #endregion
|
|
||||||
|
|
||||||
function string_quote(str) { #region
|
|
||||||
INLINE
|
|
||||||
return $"\"{str}\"";
|
|
||||||
} #endregion
|
|
|
@ -6,9 +6,9 @@ enum TEXTBOX_INPUT {
|
||||||
function textBox(_input, _onModify) : textInput(_input, _onModify) constructor {
|
function textBox(_input, _onModify) : textInput(_input, _onModify) constructor {
|
||||||
onRelease = noone;
|
onRelease = noone;
|
||||||
|
|
||||||
align = _input == TEXTBOX_INPUT.number? fa_center : fa_left;
|
align = _input == TEXTBOX_INPUT.number? fa_center : fa_left;
|
||||||
hide = false;
|
hide = false;
|
||||||
color = COLORS._main_text;
|
color = COLORS._main_text;
|
||||||
boxColor = c_white;
|
boxColor = c_white;
|
||||||
format = TEXT_AREA_FORMAT._default;
|
format = TEXT_AREA_FORMAT._default;
|
||||||
precision = 5;
|
precision = 5;
|
||||||
|
@ -497,8 +497,10 @@ function textBox(_input, _onModify) : textInput(_input, _onModify) constructor {
|
||||||
draw_set_alpha(1);
|
draw_set_alpha(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _dpx = disp_x;
|
||||||
disp_x = lerp_float(disp_x, disp_x_to, 5);
|
disp_x = lerp_float(disp_x, disp_x_to, 5);
|
||||||
|
if(_dpx != disp_x) _update = true;
|
||||||
|
|
||||||
var hoverRect = point_in_rectangle(_m[0], _m[1], _x, _y, _x + _w, _y + _h);
|
var hoverRect = point_in_rectangle(_m[0], _m[1], _x, _y, _x + _w, _y + _h);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue