Fix scaling and rotating controls
This commit is contained in:
parent
53f2addeec
commit
5051d11005
|
@ -447,6 +447,7 @@ var editor = {
|
|||
|
||||
depth++;
|
||||
render.text("$$$$$$", [0,ypos],1,editor.color_depths[depth]);
|
||||
|
||||
this.selectlist.forEach(function(x) {
|
||||
render.text(x.urstr(), x.screenpos().add([0, 32]), 1, Color.editor.ur);
|
||||
render.text(x.pos.map(function(x) { return Math.round(x); }), x.screenpos(), 1, Color.white);
|
||||
|
@ -468,7 +469,7 @@ var editor = {
|
|||
}
|
||||
|
||||
if (this.rotlist.length === 1)
|
||||
render.text(Math.trunc(this.rotlist[0].obj.angle), input.mouse.screenpos(), 1, Color.teal);
|
||||
render.text(Math.places(this.rotlist[0].angle, 3), input.mouse.screenpos(), 1, Color.teal);
|
||||
|
||||
if (this.selectlist.length === 1) {
|
||||
var i = 1;
|
||||
|
@ -639,7 +640,7 @@ editor.inputs['C-b'] = function() {
|
|||
c.grow(obj.scale);
|
||||
c.sync?.();
|
||||
});
|
||||
obj.scale = [1,1,1];
|
||||
obj.set_scale([1,1,1]);
|
||||
}
|
||||
|
||||
editor.inputs.drop = function(str) {
|
||||
|
@ -763,7 +764,7 @@ editor.inputs.m = function() {
|
|||
return;
|
||||
}
|
||||
|
||||
editor.selectlist.forEach(obj => obj.scale = [-obj.scale[0], obj.scale[1]]);
|
||||
editor.selectlist.forEach(obj => obj.grow([-1,1,1]));
|
||||
};
|
||||
editor.inputs.m.doc = "Mirror selected objects on the X axis.";
|
||||
|
||||
|
@ -798,29 +799,16 @@ editor.inputs['C-F'] = function() {
|
|||
};
|
||||
editor.inputs['C-F'].doc = "Tunnel out of the level you are editing, saving it in the process.";
|
||||
|
||||
editor.inputs['C-r'] = function() { editor.selectlist.forEach(function(x) { x.angle = -x.angle; }); };
|
||||
editor.inputs['C-r'] = function() { editor.selectlist.forEach(function(x) { x.rotate(-x.angle*2); }); }
|
||||
editor.inputs['C-r'].doc = "Negate the selected's angle.";
|
||||
|
||||
editor.inputs.r = function() {
|
||||
if (editor.sel_comp && 'angle' in editor.sel_comp) {
|
||||
var relpos = input.mouse.worldpos().sub(editor.sel_comp.gameobject.pos);
|
||||
editor.startoffset = Math.atan2(relpos.y, relpos.x);
|
||||
editor.startrot = editor.sel_comp.angle;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
editor.rotlist = [];
|
||||
editor.selectlist.forEach(function(x) {
|
||||
var relpos = input.mouse.worldpos().sub(editor.cursor);
|
||||
editor.rotlist.push({
|
||||
obj: x,
|
||||
angle: x.angle,
|
||||
pos: x.pos,
|
||||
offset: x.pos.sub(editor.cursor),
|
||||
rotoffset: Math.atan2(relpos.y, relpos.x),
|
||||
});
|
||||
});
|
||||
editor.rotlist = editor.selectlist;
|
||||
};
|
||||
editor.inputs.r.doc = "Rotate selected using the mouse while held down.";
|
||||
editor.inputs.r.released = function() { editor.rotlist = []; }
|
||||
|
@ -1160,32 +1148,25 @@ editor.inputs.mouse.move = function(pos, dpos)
|
|||
}
|
||||
|
||||
editor.grabselect?.forEach(function(x) {
|
||||
if (!x) return;
|
||||
x.move(game.camera.dir_view2world(dpos));
|
||||
x.sync();
|
||||
});
|
||||
|
||||
var relpos = input.mouse.worldpos().sub(editor.cursor);
|
||||
var dist = Vector.length(relpos);
|
||||
var lastpos = relpos.sub(dpos);
|
||||
|
||||
editor.scalelist?.forEach(function(x) {
|
||||
var scalediff = dist / x.scaleoffset;
|
||||
if (typeof x.obj.scale === 'number')
|
||||
x.obj.scale = x.scale * scalediff;
|
||||
else {
|
||||
x.obj.scale = x.scale.map(x=> x * scalediff);
|
||||
if (x.offset)
|
||||
x.obj.pos = editor.cursor.add(x.offset.scale(scalediff));
|
||||
}
|
||||
});
|
||||
var dist = Vector.length(relpos.add(dpos)) - Vector.length(relpos);
|
||||
var scalediff = 1+(dist/editor.scaleoffset);
|
||||
|
||||
editor.scalelist?.forEach(function(x) { x.grow(scalediff); });
|
||||
|
||||
var anglediff = Math.atan2(relpos.y, relpos.x) - Math.atan2(lastpos.y, lastpos.x);
|
||||
editor.rotlist?.forEach(function(x) {
|
||||
var anglediff = Math.atan2(relpos.y, relpos.x) - x.rotoffset;
|
||||
x.obj.angle = x.angle + Math.rad2turn(anglediff);
|
||||
if (input.keyboard.down('shift'))
|
||||
x.obj.angle = Math.nearest(x.obj.angle, (1/24));
|
||||
if (x.pos)
|
||||
x.obj.pos = x.pos.sub(x.offset).add(x.offset.rotate(anglediff));
|
||||
x.rotate(anglediff/(2*Math.PI));
|
||||
if (input.keyboard.down('shift')) {
|
||||
var rotate = Math.nearest(x.angle, 1/24) - x.angle;
|
||||
x.rotate(rotate)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1211,11 +1192,7 @@ editor.inputs.delete.doc = "Delete selected objects.";
|
|||
editor.inputs['S-d'] = editor.inputs.delete;
|
||||
editor.inputs['C-k'] = editor.inputs.delete;
|
||||
|
||||
editor.inputs['C-u'] = function() {
|
||||
this.selectlist.forEach(function(x) {
|
||||
x.revert();
|
||||
});
|
||||
};
|
||||
editor.inputs['C-u'] = function() { this.selectlist.forEach(x => x.revert()); };
|
||||
editor.inputs['C-u'].doc = "Revert selected objects back to their prefab form.";
|
||||
|
||||
editor.inputs['M-u'] = function() {
|
||||
|
@ -1381,27 +1358,16 @@ compmode.inputs['C-x'] = function() {};
|
|||
|
||||
editor.scalelist = [];
|
||||
editor.inputs.s = function() {
|
||||
var scaleoffset = Vector.length(input.mouse.worldpos().sub(editor.cursor));
|
||||
editor.scaleoffset = Vector.length(input.mouse.worldpos().sub(editor.cursor));
|
||||
editor.scalelist = [];
|
||||
|
||||
if (editor.sel_comp) {
|
||||
if (!('scale' in editor.sel_comp)) return;
|
||||
editor.scalelist.push({
|
||||
obj: editor.sel_comp,
|
||||
scale: editor.sel_comp.scale,
|
||||
scaleoffset: scaleoffset,
|
||||
});
|
||||
editor.scalelist.push(editor.sel_comp);
|
||||
return;
|
||||
}
|
||||
|
||||
editor.selectlist.forEach(function(x) {
|
||||
editor.scalelist.push({
|
||||
obj: x,
|
||||
scale: x.scale,
|
||||
offset: x.pos.sub(editor.cursor),
|
||||
scaleoffset: scaleoffset,
|
||||
});
|
||||
});
|
||||
editor.scalelist = editor.selectlist;
|
||||
};
|
||||
editor.inputs.s.doc = "Scale selected.";
|
||||
|
||||
|
|
|
@ -144,28 +144,38 @@ var gameobject = {
|
|||
return audio.cry(file);
|
||||
},
|
||||
|
||||
set pos(x) { this.set_pos(x); },
|
||||
get pos() { return this.rpos; },
|
||||
set angle(x) { this.set_angle(x); },
|
||||
get angle() { return this.rangle; },
|
||||
set scale(x) { this.set_scale(x); },
|
||||
get scale() { return this.rscale; },
|
||||
|
||||
set_pos(x, relative = world) {
|
||||
var move = x.sub(this.pos);
|
||||
this.pos = x;
|
||||
var newpos = x.add(relative.pos);
|
||||
var move = newpos.sub(this.pos);
|
||||
this.rpos = newpos;
|
||||
this.objects.forEach(x => x.move(move));
|
||||
},
|
||||
|
||||
set_angle(x, relative = world) {
|
||||
var diff = x - this.angle;
|
||||
this.angle = x;
|
||||
var newangle = relative.angle + x;
|
||||
var diff = newangle - this.angle;
|
||||
this.rangle = newangle;
|
||||
this.objects.forEach(obj => {
|
||||
obj.rotate(diff);
|
||||
obj.set_pos(Vector.rotate(obj.pos, diff));
|
||||
obj.set_pos(Vector.rotate(obj.get_pos(obj.master), diff), obj.master);
|
||||
});
|
||||
},
|
||||
|
||||
set_scale(x, relative = world) {
|
||||
if (typeof x === 'number') x = [x,x,x];
|
||||
var pct = this.scale.map((s,i) => x[i]/s);
|
||||
this.scale = x;
|
||||
var newscale = relative.scale.map((s,i) => x[i]*s);
|
||||
var pct = this.scale.map((s,i) => newscale[i]/s);
|
||||
this.rscale = newscale;
|
||||
this.objects.forEach(obj => {
|
||||
obj.grow(pct);
|
||||
obj.set_pos(obj.pos.map((x,i) => x*pct[i]));
|
||||
obj.set_pos(obj.get_pos(obj.master).map((x,i) => x*pct[i]), obj.master);
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -176,19 +186,22 @@ var gameobject = {
|
|||
|
||||
get_angle(relative = world) {
|
||||
if (relative === world) return this.angle;
|
||||
return this.master.angle - this.angle;
|
||||
return this.angle - relative.angle;
|
||||
},
|
||||
|
||||
get_scale(relative = world) {
|
||||
if (relative === world) return this.scale;
|
||||
var masterscale = this.master.scale;
|
||||
var masterscale = relative.scale;
|
||||
return this.scale.map((x,i) => x/masterscale[i]);
|
||||
},
|
||||
|
||||
/* Moving, rotating, scaling functions, world relative */
|
||||
move(vec) { this.set_pos(this.pos.add(vec)); },
|
||||
rotate(x) { this.set_angle(this.angle + x); },
|
||||
grow(vec) { this.set_scale(this.scale.map((x, i) => x * vec[i])); },
|
||||
grow(vec) {
|
||||
if (typeof vec === 'number') vec = [vec,vec,vec];
|
||||
this.set_scale(this.scale.map((x, i) => x * vec[i]));
|
||||
},
|
||||
|
||||
screenpos() { return game.camera.world2view(this.pos); },
|
||||
|
||||
|
@ -277,6 +290,9 @@ var gameobject = {
|
|||
if (callback) callback(ent);
|
||||
|
||||
ent.ur.fresh ??= json.decode(json.encode(ent));
|
||||
ent.ur.fresh.objects = {};
|
||||
for (var i in ent.objects)
|
||||
ent.ur.fresh.objects[i] = ent.objects[i].instance_obj();
|
||||
|
||||
return ent;
|
||||
},
|
||||
|
@ -430,11 +446,12 @@ var gameobject = {
|
|||
|
||||
transform() {
|
||||
var t = {};
|
||||
t.pos = this.pos;
|
||||
t.pos = this.get_pos(this.master);
|
||||
if (t.pos.every(x => x === 0)) delete t.pos;
|
||||
t.angle = Math.places(this.angle, 4);
|
||||
t.angle = Math.places(this.get_angle(this.master), 4);
|
||||
if (t.angle === 0) delete t.angle;
|
||||
t.scale = this.scale;
|
||||
return t;
|
||||
t.scale = this.get_scale(this.master);
|
||||
t.scale = t.scale.map((x, i) => x / this.ur.fresh.scale[i]);
|
||||
t.scale = t.scale.map(x => Math.places(x, 3));
|
||||
if (t.scale.every(x => x === 1)) delete t.scale;
|
||||
|
|
|
@ -1119,16 +1119,18 @@ static const JSCFunctionListEntry js_window_funcs[] = {
|
|||
MIST_FUNC_DEF(window, set_icon, 1)
|
||||
};
|
||||
|
||||
JSValue js_gameobject_set_pos(JSContext *js, JSValue this, JSValue val) {
|
||||
JSValue js_gameobject_set_rpos(JSContext *js, JSValue this, JSValue val) {
|
||||
cpBody *b = js2gameobject(this)->body;
|
||||
cpBodySetPosition(b, js2cvec2(val));
|
||||
if (cpBodyGetType(b) == CP_BODY_TYPE_STATIC)
|
||||
cpSpaceReindexShapesForBody(space, b);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
JSValue js_gameobject_get_pos(JSContext *js, JSValue this) { return cvec22js(cpBodyGetPosition(js2gameobject(this)->body)); }
|
||||
JSValue js_gameobject_set_angle (JSContext *js, JSValue this, JSValue val) { cpBodySetAngle(js2gameobject(this)->body, HMM_TurnToRad*js2number(val)); }
|
||||
JSValue js_gameobject_get_angle (JSContext *js, JSValue this) { return number2js(HMM_RadToTurn*cpBodyGetAngle(js2gameobject(this)->body)); }
|
||||
JSValue js_gameobject_get_rpos(JSContext *js, JSValue this) { return cvec22js(cpBodyGetPosition(js2gameobject(this)->body)); }
|
||||
JSValue js_gameobject_set_rangle (JSContext *js, JSValue this, JSValue val) { cpBodySetAngle(js2gameobject(this)->body, HMM_TurnToRad*js2number(val)); }
|
||||
JSValue js_gameobject_get_rangle (JSContext *js, JSValue this) { return number2js(HMM_RadToTurn*cpBodyGetAngle(js2gameobject(this)->body)); }
|
||||
JSValue js_gameobject_get_rscale(JSContext *js, JSValue this) { return vec32js(js2gameobject(this)->scale); }
|
||||
JSValue js_gameobject_set_rscale(JSContext *js, JSValue this, JSValue val) { js2gameobject(this)->scale = js2vec3(val); }
|
||||
JSC_GETSET_BODY(velocity, Velocity, cvec2)
|
||||
JSValue js_gameobject_set_angularvelocity (JSContext *js, JSValue this, JSValue val) { cpBodySetAngularVelocity(js2gameobject(this)->body, HMM_TurnToRad*js2number(val)); }
|
||||
JSValue js_gameobject_get_angularvelocity (JSContext *js, JSValue this) { return number2js(HMM_RadToTurn*cpBodyGetAngularVelocity(js2gameobject(this)->body)); }
|
||||
|
@ -1142,7 +1144,6 @@ JSC_GETSET_APPLY(gameobject, elasticity, number)
|
|||
JSC_GETSET_APPLY(gameobject, mass, number)
|
||||
JSC_GETSET_APPLY(gameobject, phys, number)
|
||||
JSC_GETSET_APPLY(gameobject, layer, number)
|
||||
JSC_GETSET(gameobject, scale, vec3)
|
||||
JSC_GETSET(gameobject, damping, number)
|
||||
JSC_GETSET(gameobject, timescale, number)
|
||||
JSC_GETSET(gameobject, maxvelocity, number)
|
||||
|
@ -1160,16 +1161,15 @@ static const JSCFunctionListEntry js_gameobject_funcs[] = {
|
|||
CGETSET_ADD(gameobject, elasticity),
|
||||
CGETSET_ADD(gameobject,mass),
|
||||
CGETSET_ADD(gameobject,damping),
|
||||
CGETSET_ADD(gameobject, scale),
|
||||
CGETSET_ADD(gameobject,timescale),
|
||||
CGETSET_ADD(gameobject,maxvelocity),
|
||||
CGETSET_ADD(gameobject,maxangularvelocity),
|
||||
CGETSET_ADD(gameobject,layer),
|
||||
CGETSET_ADD(gameobject,warp_filter),
|
||||
CGETSET_ADD(gameobject,scale),
|
||||
CGETSET_ADD(gameobject,drawlayer),
|
||||
CGETSET_ADD(gameobject, pos),
|
||||
CGETSET_ADD(gameobject, angle),
|
||||
CGETSET_ADD(gameobject, rpos),
|
||||
CGETSET_ADD(gameobject, rangle),
|
||||
CGETSET_ADD(gameobject, rscale),
|
||||
CGETSET_ADD(gameobject, velocity),
|
||||
CGETSET_ADD(gameobject, angularvelocity),
|
||||
CGETSET_ADD(gameobject, moi),
|
||||
|
|
Loading…
Reference in a new issue