<commit_before>import { vec2, vec3, vec4 } from 'gl-matrix';
import toNDC from '../../util/toNDC';

export default class TranslateMode {
  constructor(entity, ndc) {
    this.entity = entity;
    this.startPos = vec3.create();
    vec3.copy(this.startPos, this.entity.transform.position);

    this.mouseHeld = true;
    this.mouseX = ndc[0];
    this.mouseY = ndc[1];
    this.relativeOffset = vec2.create();

    this.align = false;
    this.alignColor = '#ff0000';
    this.alignAxis = [1, 0, 0];
  }
  enter(manager) {
    this.manager = manager;
    this.engine = manager.engine;
    this.renderer = manager.renderer;

    this.camera = this.renderer.viewports[0].camera;
    // Get relative offset
    if (this.align) {
      // We're aligning to axis - Get relative offset from origin to clicked
      // point
      // Project current model position to projection space
      // (to get Z value)
      let perspPos = vec4.fromValues(0, 0, 0, 1);
      vec4.transformMat4(perspPos, perspPos,
        this.engine.systems.matrix.get(this.entity));
      vec4.transformMat4(perspPos, perspPos,
        this.engine.systems.cameraMatrix.getProjectionView(this.camera));
      vec4.scale(perspPos, perspPos, 1 / perspPos[3]);
      // Last, store relative offset for future use
      vec2.subtract(this.relativeOffset, [this.mouseX, this.mouseY], perspPos);
    }
  }
  mousemove(e) {
    let ndc = toNDC(e.clientX, e.clientY, this.renderer);
    let deltaX = ndc[0] - this.mouseX;
    let deltaY = ndc[1] - this.mouseY;
    this.mouseX = ndc[0];
    this.mouseY = ndc[1];
    if (!this.align) {
      // Freestyle translation
      // Project current model position to projection space
      let perspPos = vec4.fromValues(0, 0, 0, 1);
      vec4.transformMat4(perspPos, perspPos,
        this.engine.systems.matrix.get(this.entity));
      vec4.transformMat4(perspPos, perspPos,
        this.engine.systems.cameraMatrix.getProjectionView(this.camera));
      // vec4.scale(perspPos, perspPos, 1 / perspPos[3]);
      // Then move using delta value
      perspPos[0] += deltaX * perspPos[3];
      perspPos[1] += deltaY * perspPos[3];
      // Inverse-project to world space
      vec4.transformMat4(perspPos, perspPos,
        this.engine.systems.cameraMatrix.getProjectionInverse(this.camera));
      vec4.transformMat4(perspPos, perspPos,
        this.engine.systems.matrix.get(this.camera));
      // Last, write the pos to transform
      this.engine.actions.transform.setPosition(this.entity, perspPos);
    } else {
      // How much should it move in viewport space in order to move (1, 0, 0)?
      // Project current model position to projection space
      let perspPos = vec4.fromValues(0, 0, 0, 1);
      vec3.copy(perspPos, this.startPos);
      let addedPos = vec4.create();
      addedPos[3] = 1;
      vec3.add(addedPos, perspPos, this.alignAxis);
      vec4.transformMat4(perspPos, perspPos,
        this.engine.systems.cameraMatrix.getProjectionView(this.camera));
      vec4.transformMat4(addedPos, addedPos,
        this.engine.systems.cameraMatrix.getProjectionView(this.camera));
      let centerPos = vec2.create();
      vec2.copy(centerPos, perspPos);
      vec2.scale(centerPos, centerPos, 1 / perspPos[3]);
      let dirPos = vec2.create();
      vec2.copy(dirPos, addedPos);
      vec2.scale(dirPos, dirPos, 1 / addedPos[3]);
      vec2.subtract(dirPos, dirPos, centerPos);
      let dirNorm = vec2.create();
      vec2.normalize(dirNorm, dirPos);
      // Now we've got everything, calculated required transform length
      // and translate to it
      let projected = vec2.create();
      vec2.subtract(projected, ndc, centerPos);
      vec2.subtract(projected, projected, this.relativeOffset);
      let dist = vec2.dot(projected, dirNorm);
      let transSize = dist / vec2.length(dirPos);
      let translation = vec3.create();
      vec3.copy(translation, this.alignAxis);
      vec3.scale(translation, translation, transSize);
      let pos = vec3.create();
      vec3.add(pos, translation, this.startPos);
      // Last, write the pos to transform
      this.engine.actions.transform.setPosition(this.entity, pos);
    }
  }<commit_msg>Improve object translation algorithm<commit_after>import { vec2, vec3, vec4 } from 'gl-matrix';
import toNDC from '../../util/toNDC';

export default class TranslateMode {
  constructor(entity, ndc) {
    this.entity = entity;
    this.startPos = vec3.create();
    vec3.copy(this.startPos, this.entity.transform.position);

    this.mouseHeld = true;
    this.mouseX = ndc[0];
    this.mouseY = ndc[1];
    this.relativeOffset = vec2.create();

    this.align = false;
    this.alignColor = '#ff0000';
    this.alignAxis = [1, 0, 0];
  }
  enter(manager) {
    this.manager = manager;
    this.engine = manager.engine;
    this.renderer = manager.renderer;

    this.camera = this.renderer.viewports[0].camera;
  }
  mousemove(e) {
    let ndc = toNDC(e.clientX, e.clientY, this.renderer);
    let deltaX = ndc[0] - this.mouseX;
    let deltaY = ndc[1] - this.mouseY;
    this.mouseX = ndc[0];
    this.mouseY = ndc[1];
    if (!this.align) {
      // Freestyle translation
      // Project current model position to projection space
      let perspPos = vec4.fromValues(0, 0, 0, 1);
      vec4.transformMat4(perspPos, perspPos,
        this.engine.systems.matrix.get(this.entity));
      vec4.transformMat4(perspPos, perspPos,
        this.engine.systems.cameraMatrix.getProjectionView(this.camera));
      // vec4.scale(perspPos, perspPos, 1 / perspPos[3]);
      // Then move using delta value
      perspPos[0] += deltaX * perspPos[3];
      perspPos[1] += deltaY * perspPos[3];
      // Inverse-project to world space
      vec4.transformMat4(perspPos, perspPos,
        this.engine.systems.cameraMatrix.getProjectionInverse(this.camera));
      vec4.transformMat4(perspPos, perspPos,
        this.engine.systems.matrix.get(this.camera));
      // Last, write the pos to transform
      this.engine.actions.transform.setPosition(this.entity, perspPos);
    } else {
      // Project current model position to projection space
      let perspPos = vec4.fromValues(0, 0, 0, 1);
      vec3.copy(perspPos, this.startPos);
      let addedPos = vec4.create();
      vec3.copy(addedPos, this.alignAxis);
      vec4.transformMat4(perspPos, perspPos,
        this.engine.systems.cameraMatrix.getProjectionView(this.camera));
      vec4.transformMat4(addedPos, addedPos,
        this.engine.systems.cameraMatrix.getProjectionView(this.camera));
      // Use biggest value of X or Y, since too low value can lead to
      // division by zero or something
      let index = Math.abs(addedPos[0]) > Math.abs(addedPos[1]) ? 0 : 1;
      // n = (x0-w0 x)/(x ω1-x1)
      let distance = (perspPos[index] - perspPos[3] * ndc[index]) /
        (addedPos[3] * ndc[index] - addedPos[index]);
      let translation = vec3.create();
      vec3.copy(translation, this.alignAxis);
      vec3.scale(translation, translation, distance);
      let pos = vec3.create();
      vec3.add(pos, translation, this.startPos);
      // Last, write the pos to transform
      this.engine.actions.transform.setPosition(this.entity, pos);
    }
  }
{'fraction_non_alphanumeric': 0.12905020164094005, 'fraction_numerical': 0.02225003476567932, 'mean_word_length': 2.917211328976035, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2943991', 'n_tokens_mistral': 2400, 'n_tokens_neox': 2348, 'n_words': 508}