Search in sources :

Example 1 with Keyframe

use of gaiasky.desktop.util.camera.Keyframe in project gaiasky by langurmonkey.

the class KeyframesPathObject method refreshOrientations.

/**
 * Refreshes the orientations from the keyframes
 */
public void refreshOrientations() {
    int i = 0;
    for (Keyframe kf : keyframes) {
        VertsObject dir = orientations.get(i);
        VertsObject up = orientations.get(i + 1);
        refreshSingleVector(dir, kf.pos, kf.dir);
        refreshSingleVector(up, kf.pos, kf.up);
        i += 2;
    }
}
Also used : Keyframe(gaiasky.desktop.util.camera.Keyframe)

Example 2 with Keyframe

use of gaiasky.desktop.util.camera.Keyframe in project gaiasky by langurmonkey.

the class KeyframesPathObject method unselect.

public void unselect() {
    if (selected != null) {
        int i = keyframes.indexOf(selected, true) * 2;
        if (i >= 0) {
            VertsObject dir = orientations.get(i);
            VertsObject up = orientations.get(i + 1);
            dir.setPrimitiveSize(0.6f * ss);
            up.setPrimitiveSize(0.6f * ss);
        }
        initFocus();
        focus.setName("");
        Keyframe aux = selected;
        selected = null;
        selectedKnot.clear();
        EventManager.publish(Event.KEYFRAME_UNSELECT, this, aux);
    }
}
Also used : Keyframe(gaiasky.desktop.util.camera.Keyframe)

Example 3 with Keyframe

use of gaiasky.desktop.util.camera.Keyframe in project gaiasky by langurmonkey.

the class KeyframesWindow method build.

@Override
protected void build() {
    /*
         * Right and left tables
         */
    Table left = new Table(skin);
    left.align(Align.top | Align.left);
    Table right = new Table(skin);
    right.align(Align.top | Align.left);
    /* LEFT - CONTROLS */
    // ADD
    OwnTextIconButton addKeyframe = new OwnTextIconButton(I18n.txt("gui.keyframes.add.end"), skin, "add");
    addKeyframe.addListener(new OwnTextTooltip(I18n.txt("gui.tooltip.kf.add.end"), skin));
    addKeyframe.pad(pad5);
    left.add(addKeyframe).left().colspan(2).padBottom(pad5).row();
    addKeyframe.addListener(event -> {
        if (event instanceof ChangeEvent) {
            // Add at end
            return addKeyframe(-1);
        }
        return false;
    });
    // SECONDS
    FloatValidator secondsValidator = new FloatValidator(0.0001f, 9999.0f);
    secondsValidator.setIsValidCallback(() -> {
        // Enable add button
        addKeyframe.setDisabled(false);
    });
    secondsValidator.setIsInvalidCallback(() -> {
        // Disable add button
        addKeyframe.setDisabled(true);
    });
    secondsInput = new OwnTextField("1.0", skin, secondsValidator);
    secondsInput.setWidth(96f);
    OwnLabel secondsLabel = new OwnLabel(I18n.txt("gui.keyframes.secsafter") + ":", skin);
    left.add(secondsLabel).center().left().padRight(pad10).padBottom(pad10);
    left.add(secondsInput).center().left().padBottom(pad10).row();
    // NAME
    LengthValidator lengthValidator = new LengthValidator(0, 15);
    RegexpValidator nameValidator = new RegexpValidator(lengthValidator, "^[^*&%\\s\\+\\=\\\\\\/@#\\$&\\*()~]*$");
    nameInput = new OwnTextField("", skin, nameValidator);
    nameInput.setWidth(96f);
    OwnLabel nameLabel = new OwnLabel(I18n.txt("gui.keyframes.name") + ":", skin);
    left.add(nameLabel).center().left().padRight(pad10).padBottom(pad10);
    left.add(nameInput).center().left().padBottom(pad10).row();
    left.pack();
    /* RIGHT - KEYFRAMES */
    OwnLabel keyframesTitle = new OwnLabel(I18n.txt("gui.keyframes.list"), skin, "hud-header");
    // KEYFRAMES TABLE
    keyframesTable = buildKeyframesTable();
    // ADD SCROLL
    rightScroll = new OwnScrollPane(keyframesTable, skin, "minimalist-nobg");
    rightScroll.setExpand(true);
    rightScroll.setScrollingDisabled(true, false);
    rightScroll.setHeight(160f);
    rightScroll.setWidth(540f);
    rightScroll.setFadeScrollBars(true);
    right.add(keyframesTitle).top().left().padBottom(pad10).row();
    right.add(rightScroll).center().left();
    right.pack();
    /* RE-NORMALIZE TIME */
    OwnTextButton normalizeTime = new OwnTextButton(I18n.txt("gui.keyframes.normalize"), skin);
    normalizeTime.addListener(new OwnTextTooltip(I18n.txt("gui.tooltip.kf.normalize"), skin));
    normalizeTime.pad(pad10);
    normalizeTime.addListener((event) -> {
        if (event instanceof ChangeEvent) {
            if (keyframes != null && keyframes.size > 2) {
                Vector3d aux = new Vector3d();
                int n = keyframes.size;
                double totalTime = 0;
                double totalDist = 0;
                for (int i = 1; i < n; i++) {
                    Keyframe kf0 = keyframes.get(i - 1);
                    Keyframe kf1 = keyframes.get(i);
                    totalTime += kf1.seconds;
                    totalDist += aux.set(kf1.pos).sub(kf0.pos).len();
                }
                // Loop over keyframes and assign new times
                for (int i = 1; i < n; i++) {
                    Keyframe kf0 = keyframes.get(i - 1);
                    Keyframe kf1 = keyframes.get(i);
                    double dist = aux.set(kf1.pos).sub(kf0.pos).len();
                    kf1.seconds = totalTime * dist / totalDist;
                }
                // Reload window contents
                reinitialiseKeyframes(keyframes, null);
                keyframesPathObject.unselect();
                logger.info(I18n.txt("gui.keyframes.normalize.done"));
            }
            return true;
        }
        return false;
    });
    /* ACTION BUTTONS */
    HorizontalGroup buttons = new HorizontalGroup();
    buttons.space(pad10);
    // Open keyframes
    OwnTextIconButton open = new OwnTextIconButton(I18n.txt("gui.keyframes.load"), skin, "open");
    open.addListener(new OwnTextTooltip(I18n.txt("gui.tooltip.kf.load"), skin));
    open.pad(pad5);
    open.addListener((event) -> {
        if (event instanceof ChangeEvent) {
            FileChooser fc = new FileChooser(I18n.txt("gui.download.pickloc"), skin, stage, SysUtils.getDefaultCameraDir(), FileChooser.FileChooserTarget.FILES);
            fc.setShowHidden(Settings.settings.program.fileChooser.showHidden);
            fc.setShowHiddenConsumer((showHidden) -> Settings.settings.program.fileChooser.showHidden = showHidden);
            fc.setFileFilter(pathname -> pathname.getFileName().toString().endsWith(".gkf"));
            fc.setAcceptedFiles("*.gkf");
            fc.setResultListener((success, result) -> {
                if (success) {
                    if (Files.exists(result) && Files.isRegularFile(result)) {
                        // Load selected file
                        try {
                            Array<Keyframe> kfs = CameraKeyframeManager.instance.loadKeyframesFile(result);
                            // Update current instance
                            reinitialiseKeyframes(kfs, null);
                            keyframesPathObject.unselect();
                            lastKeyframeFileName = result.getFileName().toString();
                            logger.info(I18n.txt("gui.keyframes.load.success", keyframes.size, result.getFileName()));
                        } catch (RuntimeException e) {
                            logger.error(I18n.txt("gui.keyframes.load.error", result.getFileName()), e);
                            Label warn = new OwnLabel(I18n.txt("error.loading.format", result.getFileName()), skin);
                            warn.setColor(1f, .4f, .4f, 1f);
                            notice.setActor(warn);
                            return false;
                        }
                    } else {
                        logger.error(I18n.txt("error.loading.notexistent", result.getFileName()));
                        Label warn = new OwnLabel(I18n.txt("error.loading.notexistent", result.getFileName()), skin);
                        warn.setColor(1f, .4f, .4f, 1f);
                        notice.setActor(warn);
                        return false;
                    }
                }
                notice.clearActor();
                return true;
            });
            fc.show(stage);
            return true;
        }
        return false;
    });
    // Save keyframes
    OwnTextIconButton save = new OwnTextIconButton(I18n.txt("gui.keyframes.save"), skin, "save");
    save.addListener(new OwnTextTooltip(I18n.txt("gui.tooltip.kf.save"), skin));
    save.pad(pad5);
    save.addListener((event) -> {
        if (event instanceof ChangeEvent) {
            String suggestedName = lastKeyframeFileName == null ? df.format(new Date()) + "_keyframes.gkf" : lastKeyframeFileName;
            FileNameWindow fnw = new FileNameWindow(suggestedName, stage, skin);
            OwnTextField textField = fnw.getFileNameField();
            fnw.setAcceptRunnable(() -> {
                if (textField.isValid()) {
                    EventManager.publish(Event.KEYFRAMES_FILE_SAVE, fnw, keyframes, textField.getText());
                    lastKeyframeFileName = textField.getText();
                    notice.clearActor();
                } else {
                    Label warn = new OwnLabel(I18n.txt("error.file.name.notvalid", textField.getText()), skin);
                    warn.setColor(1f, .4f, .4f, 1f);
                    notice.setActor(warn);
                }
            });
            fnw.show(stage);
            return true;
        }
        return false;
    });
    // Export to camera path
    OwnTextIconButton export = new OwnTextIconButton(I18n.txt("gui.keyframes.export"), skin, "export");
    export.addListener(new OwnTextTooltip(I18n.txt("gui.tooltip.kf.export"), skin));
    export.pad(pad5);
    export.addListener((event) -> {
        if (event instanceof ChangeEvent) {
            String suggestedName = df.format(new Date()) + ".gsc";
            FileNameWindow fnw = new FileNameWindow(suggestedName, stage, skin);
            OwnTextField textField = fnw.getFileNameField();
            fnw.setAcceptRunnable(() -> {
                if (textField.isValid()) {
                    EventManager.publish(Event.KEYFRAMES_EXPORT, fnw, keyframes, textField.getText());
                    notice.clearActor();
                } else {
                    Label warn = new OwnLabel(I18n.txt("error.file.name.notvalid", textField.getText()), skin);
                    warn.setColor(1f, .4f, .4f, 1f);
                    notice.setActor(warn);
                }
            });
            fnw.show(stage);
            return true;
        }
        return false;
    });
    // Keyframe preferences
    Button preferences = new OwnTextIconButton(I18n.txt("gui.preferences"), skin, "preferences");
    preferences.setName("keyframe preferences");
    preferences.pad(pad5);
    preferences.addListener(new OwnTextTooltip(I18n.txt("gui.tooltip.kf.editprefs"), skin));
    preferences.addListener((event) -> {
        if (event instanceof ChangeEvent) {
            KeyframePreferencesWindow kpw = new KeyframePreferencesWindow(stage, skin);
            kpw.setAcceptRunnable(() -> {
                // Resample
                GaiaSky.postRunnable(() -> {
                    keyframesPathObject.resamplePath();
                });
            });
            kpw.setCancelRunnable(() -> {
            });
            kpw.show(stage, me.getWidth(), 0);
            return true;
        }
        return false;
    });
    buttons.addActor(open);
    buttons.addActor(save);
    buttons.addActor(export);
    buttons.addActor(preferences);
    /* FINAL LAYOUT */
    content.add(left).top().left().padRight(pad10 * 2f).padBottom(pad10 * 3f);
    content.add(right).width(592f).top().left().padBottom(pad10).row();
    notice = content.add();
    notice.padBottom(pad10 * 2f).expandY().center().colspan(2).row();
    content.add(normalizeTime).colspan(2).bottom().center().padBottom(pad10).row();
    content.add(buttons).colspan(2).bottom().right().row();
    // CLEAR
    OwnTextButton clear = new OwnTextButton(I18n.txt("gui.clear"), skin);
    clear.setName("clear");
    clear.addListener((event) -> {
        if (event instanceof ChangeEvent) {
            GaiaSky.postRunnable(this::clean);
            return true;
        }
        return false;
    });
    buttonGroup.addActorAt(0, clear);
    // HIDE
    OwnTextButton hide = new OwnTextButton(I18n.txt("gui.hide"), skin);
    hide.setName("hide");
    hide.addListener((event) -> {
        if (event instanceof ChangeEvent) {
            hide();
            return true;
        }
        return false;
    });
    buttonGroup.addActorAt(1, hide);
    recalculateButtonSize();
}
Also used : LengthValidator(gaiasky.util.validator.LengthValidator) Keyframe(gaiasky.desktop.util.camera.Keyframe) FloatValidator(gaiasky.util.validator.FloatValidator) RegexpValidator(gaiasky.util.validator.RegexpValidator) Date(java.util.Date) ChangeEvent(com.badlogic.gdx.scenes.scene2d.utils.ChangeListener.ChangeEvent) Vector3d(gaiasky.util.math.Vector3d)

Example 4 with Keyframe

use of gaiasky.desktop.util.camera.Keyframe in project gaiasky by langurmonkey.

the class KeyframesWindow method addKeyframeToTable.

private void addKeyframeToTable(Keyframe kf, double prevT, int index, Table table, boolean addToModel) {
    // Seconds
    addFrameSeconds(kf, prevT, index, table);
    // Frame number
    double t = 0;
    for (int i = 0; ; i++) {
        if (keyframes.get(i).equals(kf))
            break;
        t += keyframes.get(i).seconds;
    }
    long frame = (long) ((t + kf.seconds) * Settings.settings.frame.targetFps);
    OwnLabel framesL = new OwnLabel("(" + frame + ")", skin);
    framesL.setWidth(64f);
    framesL.addListener(new OwnTextTooltip(I18n.txt("gui.tooltip.kf.frames", frame, (1d / Settings.settings.frame.targetFps)), skin));
    addHighlightListener(framesL, kf);
    table.add(framesL).left().padRight(pad10).padBottom(pad5);
    // Clock - time
    Image clockimg = new Image(skin.getDrawable("clock"));
    clockimg.addListener(new OwnTextTooltip(dateFormat.format(Instant.ofEpochMilli(kf.time)), skin));
    clockimg.setScale(0.7f);
    clockimg.setOrigin(Align.center);
    addHighlightListener(clockimg, kf);
    table.add(clockimg).width(clockimg.getWidth()).left().padRight(pad10).padBottom(pad5);
    // Frame name
    addFrameName(kf, index, table);
    // Go to
    OwnTextIconButton goTo = new OwnTextIconButton("", skin, "go-to");
    goTo.setSize(buttonSize, buttonSize);
    goTo.addListener(new OwnTextTooltip(I18n.txt("gui.tooltip.kf.goto"), skin));
    goTo.addListener((event) -> {
        if (event instanceof ChangeEvent) {
            // Go to keyframe
            EventManager.publish(Event.CAMERA_MODE_CMD, CameraManager.CameraMode.FREE_MODE);
            GaiaSky.postRunnable(() -> {
                EventManager.publish(Event.CAMERA_POS_CMD, goTo, (Object) kf.pos.values());
                EventManager.publish(Event.CAMERA_DIR_CMD, goTo, (Object) kf.dir.values());
                EventManager.publish(Event.CAMERA_UP_CMD, goTo, (Object) kf.up.values());
                EventManager.publish(Event.TIME_CHANGE_CMD, goTo, Instant.ofEpochMilli(kf.time));
            });
            return true;
        }
        return false;
    });
    addHighlightListener(goTo, kf);
    table.add(goTo).left().padRight(pad5).padBottom(pad5);
    // Seam
    OwnTextIconButton seam = new OwnTextIconButton("", skin, "seam", "toggle");
    seam.setSize(buttonSize, buttonSize);
    seam.setChecked(kf.seam);
    seam.addListener(new OwnTextTooltip(I18n.txt("gui.tooltip.kf.seam"), skin));
    seam.addListener((event) -> {
        if (event instanceof ChangeEvent) {
            // Make seam
            kf.seam = seam.isChecked();
            GaiaSky.postRunnable(() -> {
                keyframesPathObject.refreshData();
                if (keyframesPathObject.selected == kf) {
                    if (seam.isChecked())
                        keyframesPathObject.selectedKnot.setColor(ColorUtils.gRed);
                    else
                        keyframesPathObject.selectedKnot.setColor(ColorUtils.gWhite);
                }
            });
            return true;
        }
        return false;
    });
    addHighlightListener(seam, kf);
    table.add(seam).left().padRight(pad5).padBottom(pad5);
    // Add after
    OwnTextIconButton addKeyframe = new OwnTextIconButton("", skin, "add");
    addKeyframe.setSize(buttonSizeL, buttonSize);
    addKeyframe.addListener(new OwnTextTooltip(I18n.txt("gui.tooltip.kf.add.after"), skin));
    addKeyframe.addListener(event -> {
        if (event instanceof ChangeEvent) {
            // Work out keyframe properties
            Keyframe k0, k1;
            Vector3d pos, dir, up;
            long time;
            if (index < keyframes.size - 1) {
                // We can interpolate
                k0 = keyframes.get(index);
                k1 = keyframes.get(index + 1);
                pos = new Vector3d().set(k0.pos).interpolate(k1.pos, 0.5, Interpolationd.linear);
                dir = new Vector3d().set(k0.dir).interpolate(k1.dir, 0.5, Interpolationd.linear);
                up = new Vector3d().set(k0.up).interpolate(k1.up, 0.5, Interpolationd.linear);
                time = k0.time + (long) ((k1.time - k0.time) / 2d);
            } else {
                // Last keyframe
                k0 = keyframes.get(index - 1);
                k1 = keyframes.get(index);
                pos = new Vector3d().set(k0.pos).interpolate(k1.pos, 1.5, Interpolationd.linear);
                dir = new Vector3d().set(k0.dir).interpolate(k1.dir, 1.5, Interpolationd.linear);
                up = new Vector3d().set(k0.up).interpolate(k1.up, 1.5, Interpolationd.linear);
                time = k1.time + (long) ((k1.time - k0.time) / 2d);
            }
            // Add at end
            return addKeyframe(index + 1, pos, dir, up, time);
        }
        return false;
    });
    addHighlightListener(addKeyframe, kf);
    table.add(addKeyframe).left().padRight(pad5).padBottom(pad5);
    // Rubbish
    OwnTextIconButton rubbish = new OwnTextIconButton("", skin, "rubbish");
    rubbish.setSize(buttonSizeL, buttonSize);
    rubbish.addListener(new OwnTextTooltip(I18n.txt("gui.tooltip.kf.remove"), skin));
    rubbish.addListener((event) -> {
        if (event instanceof ChangeEvent) {
            // Remove keyframe
            Array<Keyframe> newKfs = new Array<>(false, keyframes.size - 1);
            for (Keyframe k : keyframes) {
                if (k != kf)
                    newKfs.add(k);
            }
            // In case we removed the first
            if (!newKfs.isEmpty())
                newKfs.get(0).seconds = 0;
            reinitialiseKeyframes(newKfs, null);
            logger.info(I18n.txt("gui.keyframes.removed", kf.name));
            return true;
        }
        return false;
    });
    addHighlightListener(rubbish, kf);
    Cell<?> rub = table.add(rubbish).left().padBottom(pad5);
    rub.row();
    table.pack();
    if (addToModel && keyframesPathObject != null) {
        GaiaSky.postRunnable(() -> {
            // Update model data
            keyframesPathObject.addKnot(kf.pos, kf.dir, kf.up, kf.seam);
            keyframesPathObject.segments.addPoint(kf.pos);
            if (keyframes.size > 1)
                keyframesPathObject.resamplePath();
        });
    }
}
Also used : Array(com.badlogic.gdx.utils.Array) ChangeEvent(com.badlogic.gdx.scenes.scene2d.utils.ChangeListener.ChangeEvent) Keyframe(gaiasky.desktop.util.camera.Keyframe) Vector3d(gaiasky.util.math.Vector3d)

Example 5 with Keyframe

use of gaiasky.desktop.util.camera.Keyframe in project gaiasky by langurmonkey.

the class KeyframesWindow method addKeyframe.

/**
 * Adds a new keyframe at the given index position using the given camera position, orientation and time
 *
 * @param index The position of the keyframe, negative to add at the end
 * @param cPos  The position
 * @param cDir  The direction
 * @param cUp   The up
 * @param cTime The time
 * @return True if the keyframe was added, false otherwise
 */
private boolean addKeyframe(int index, Vector3d cPos, Vector3d cDir, Vector3d cUp, long cTime) {
    try {
        boolean secOk = secondsInput.isValid();
        boolean nameOk = nameInput.isValid();
        if (secOk && nameOk) {
            // Seconds after - first keyframe at zero
            double secsAfter = keyframes.size == 0 ? 0 : Double.parseDouble(secondsInput.getText());
            // Name
            String name;
            String ni = nameInput.getText();
            if (ni != null && !ni.isEmpty()) {
                name = ni;
            } else {
                name = "Keyframe " + (keyframes.size + 1);
            }
            Keyframe kf = new Keyframe(name, cPos, cDir, cUp, cTime, secsAfter, false);
            final boolean insert = index >= 0 && index != keyframes.size;
            if (!insert) {
                keyframes.add(kf);
                double prevT = 0;
                for (Keyframe kfr : keyframes) {
                    if (kfr == kf)
                        break;
                    prevT += kfr.seconds;
                }
                addKeyframeToTable(kf, prevT, keyframes.size - 1, keyframesTable, true);
            } else {
                keyframes.insert(index, kf);
            }
            GaiaSky.postRunnable(() -> {
                if (insert)
                    reinitialiseKeyframes(keyframes, kf);
                scrollToKeyframe(kf);
            });
        } else {
            logger.info(I18n.txt("gui.keyframes.notadded") + "-" + I18n.txt("gui.keyframes.error.values", secOk ? I18n.txt("gui.ok") : I18n.txt("gui.wrong"), nameOk ? I18n.txt("gui.ok") : I18n.txt("gui.wrong")));
        }
    } catch (Exception e) {
        logger.error(I18n.txt("gui.keyframes.notadded") + " - " + I18n.txt("gui.keyframes.error.input"), e);
        return false;
    }
    return true;
}
Also used : Keyframe(gaiasky.desktop.util.camera.Keyframe)

Aggregations

Keyframe (gaiasky.desktop.util.camera.Keyframe)10 Vector3d (gaiasky.util.math.Vector3d)5 Array (com.badlogic.gdx.utils.Array)3 ChangeEvent (com.badlogic.gdx.scenes.scene2d.utils.ChangeListener.ChangeEvent)2 PerspectiveCamera (com.badlogic.gdx.graphics.PerspectiveCamera)1 Vector3 (com.badlogic.gdx.math.Vector3)1 FloatValidator (gaiasky.util.validator.FloatValidator)1 LengthValidator (gaiasky.util.validator.LengthValidator)1 RegexpValidator (gaiasky.util.validator.RegexpValidator)1 Date (java.util.Date)1