From cbad4bcea134b6faf044fa37d7c994647ac8c197 Mon Sep 17 00:00:00 2001 From: iChun Date: Sun, 28 Nov 2021 15:29:23 +0800 Subject: [PATCH] Bump version to 1.5.0. Add HandInfo exporter. --- build.gradle | 4 +- .../mods/tabula/client/export/ExportList.java | 1 + .../client/export/types/ExportHandInfo.java | 76 +++ .../types/handInfo/WindowExportHandInfo.java | 590 ++++++++++++++++++ .../window/popup/WindowExportHeadInfo.java | 5 +- .../window/popup/WindowImportMCProject.java | 1 + src/main/resources/PlayerGhost.tbl | Bin 0 -> 3185 bytes .../resources/assets/tabula/lang/en_us.json | 6 + 8 files changed, 680 insertions(+), 3 deletions(-) create mode 100644 src/main/java/me/ichun/mods/tabula/client/export/types/ExportHandInfo.java create mode 100644 src/main/java/me/ichun/mods/tabula/client/export/types/handInfo/WindowExportHandInfo.java create mode 100644 src/main/resources/PlayerGhost.tbl diff --git a/build.gradle b/build.gradle index fac559d..db906f6 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ apply plugin: 'net.minecraftforge.gradle' apply plugin: 'eclipse' apply plugin: 'maven-publish' -version = '10.4.0' +version = '10.5.0' group = 'tabula' archivesBaseName = 'Tabula-1.16.5' @@ -69,7 +69,7 @@ dependencies { // that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied. // The userdev artifact is a special name and will get all sorts of transformations applied to it. minecraft 'net.minecraftforge:forge:1.16.5-36.0.55' - implementation fg.deobf("ichunutil:iChunUtil:10.4.0") + implementation fg.deobf("ichunutil:iChunUtil:10.5.0") // You may put jars on which you depend on in ./libs or you may define them like so.. // compile "some.group:artifact:version:classifier" diff --git a/src/main/java/me/ichun/mods/tabula/client/export/ExportList.java b/src/main/java/me/ichun/mods/tabula/client/export/ExportList.java index 88d28de..7d96721 100644 --- a/src/main/java/me/ichun/mods/tabula/client/export/ExportList.java +++ b/src/main/java/me/ichun/mods/tabula/client/export/ExportList.java @@ -10,6 +10,7 @@ public final class ExportList { public static final TreeMap EXPORTERS = new TreeMap(Comparator.naturalOrder()) {{ put("blockJson", new ExportBlockJson()); + put("handInfo", new ExportHandInfo()); put("headInfo", new ExportHeadInfo()); put("javaClass", new ExportJava()); put("projectTexture", new ExportProjectTexture()); diff --git a/src/main/java/me/ichun/mods/tabula/client/export/types/ExportHandInfo.java b/src/main/java/me/ichun/mods/tabula/client/export/types/ExportHandInfo.java new file mode 100644 index 0000000..7645e18 --- /dev/null +++ b/src/main/java/me/ichun/mods/tabula/client/export/types/ExportHandInfo.java @@ -0,0 +1,76 @@ +package me.ichun.mods.tabula.client.export.types; + +import com.google.common.base.Splitter; +import me.ichun.mods.ichunutil.api.client.hand.HandInfo; +import me.ichun.mods.ichunutil.client.gui.bns.Workspace; +import me.ichun.mods.ichunutil.common.head.HeadHandler; +import me.ichun.mods.ichunutil.common.module.tabula.formats.types.Exporter; +import me.ichun.mods.ichunutil.common.module.tabula.project.Project; +import me.ichun.mods.tabula.client.core.ResourceHelper; +import me.ichun.mods.tabula.client.export.types.handInfo.WindowExportHandInfo; +import me.ichun.mods.tabula.client.gui.WorkspaceTabula; +import me.ichun.mods.tabula.client.tabula.Mainframe; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.I18n; +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.util.List; + +public class ExportHandInfo extends Exporter +{ + public ExportHandInfo() + { + super(I18n.format("tabula.export.handInfo.name")); + } + + @Override + public String getId() + { + return "handInfo"; + } + + @Override + public boolean override(Workspace workspace, Project project) + { + Mainframe.ProjectInfo activeProject = ((WorkspaceTabula)workspace).mainframe.getActiveProject(); + if(activeProject != null) + { + WindowExportHandInfo.open((WorkspaceTabula)workspace, activeProject); + } + + return true; + } + + @Override + public boolean export(Project project, Object... params) + { + HandInfo info = (HandInfo)params[0]; + + if(!Minecraft.getInstance().getSession().getUsername().equals("Dev")) + { + info.author = Minecraft.getInstance().getSession().getUsername(); + } + + List strings = Splitter.on(".").trimResults().omitEmptyStrings().splitToList(info.forClass); + + if(strings.isEmpty()) + { + strings.add("NO_CLASS_DEFINED"); + } + + File file = new File(ResourceHelper.getExportsDir().toFile(), strings.get(strings.size() - 1) + ".json"); + try + { + String json = HeadHandler.GSON.toJson(info, HandInfo.class); + FileUtils.writeStringToFile(file, json, "UTF-8"); + return true; + } + catch(Throwable e1) + { + e1.printStackTrace(); + } + + return false; //Export is done by the window. We forget about it here. + } +} diff --git a/src/main/java/me/ichun/mods/tabula/client/export/types/handInfo/WindowExportHandInfo.java b/src/main/java/me/ichun/mods/tabula/client/export/types/handInfo/WindowExportHandInfo.java new file mode 100644 index 0000000..4ecf09f --- /dev/null +++ b/src/main/java/me/ichun/mods/tabula/client/export/types/handInfo/WindowExportHandInfo.java @@ -0,0 +1,590 @@ +package me.ichun.mods.tabula.client.export.types.handInfo; + +import me.ichun.mods.ichunutil.api.client.hand.HandInfo; +import me.ichun.mods.ichunutil.api.common.PlacementCorrector; +import me.ichun.mods.ichunutil.client.gui.bns.window.Window; +import me.ichun.mods.ichunutil.client.gui.bns.window.WindowPopup; +import me.ichun.mods.ichunutil.client.gui.bns.window.constraint.Constraint; +import me.ichun.mods.ichunutil.client.gui.bns.window.view.View; +import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.*; +import me.ichun.mods.ichunutil.common.module.tabula.formats.ImportList; +import me.ichun.mods.ichunutil.common.module.tabula.project.Project; +import me.ichun.mods.tabula.client.export.ExportList; +import me.ichun.mods.tabula.client.gui.WorkspaceTabula; +import me.ichun.mods.tabula.client.tabula.Mainframe; +import me.ichun.mods.tabula.common.Tabula; +import net.minecraft.client.resources.I18n; +import net.minecraft.util.HandSide; + +import javax.annotation.Nonnull; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.Locale; +import java.util.function.Consumer; + +public class WindowExportHandInfo extends Window +{ + public final Mainframe.ProjectInfo projectInfo; + public LinkedHashSet leftParts; + public LinkedHashSet rightParts; + public ArrayList alignedLeft; + public ArrayList alignedRight; + + public WindowExportHandInfo(WorkspaceTabula parent, Mainframe.ProjectInfo project) + { + super(parent); + + this.projectInfo = project; + + disableDockingEntirely(); + } + + public static WindowExportHandInfo open(WorkspaceTabula parent, Mainframe.ProjectInfo project) + { + project.selectPart(null); //Deselect any currently selected parts. + + WindowExportHandInfo window = new WindowExportHandInfo(parent, project); + window.setView(new ViewSelectParts(window, HandSide.LEFT)); + window.pos(0, 20); + window.size(180, parent.getHeight() - 20); + parent.addWindow(window); + parent.setListener(window); + window.init(); + return window; + } + + public void nextStep() + { + if(currentView instanceof ViewSelectParts) + { + ViewSelectParts view = (ViewSelectParts)currentView; + if(view.handSide == HandSide.LEFT) + { + leftParts = view.parts; + projectInfo.selectPart(null); + setView(new ViewSelectParts(this, HandSide.RIGHT)); + getCurrentView().init(); + setListener(getCurrentView()); + } + else + { + rightParts = view.parts; + //load player ghost + InputStream in = Tabula.class.getResourceAsStream("/PlayerGhost.tbl"); + if(in != null) + { + Project ghost = ImportList.IMPORTER_TABULA.createProject(in); + if(ghost != null) + { + ghost.projVersion = ImportList.IMPORTER_TABULA.getProjectVersion(); + ghost.load(); + + projectInfo.setGhostProject(ghost, 0.2F); + } + } + + //Delete all the non-relevant parts + ArrayList parts = new ArrayList<>(projectInfo.project.parts); + for(Project.Part part : parts) + { + if(!(leftParts.contains(part) || rightParts.contains(part))) + { + projectInfo.delete(part); + } + } + + for(Project.Part leftPart : leftParts) + { + leftPart.rotAX = 0F; + parent.mainframe.updatePart(leftPart, true); + } + + for(Project.Part rightPart : rightParts) + { + rightPart.rotAX = 0F; + + if(!leftParts.contains(rightPart)) + { + rightPart.showModel = false; + } + + parent.mainframe.updatePart(rightPart, true); + } + + alignedLeft = new ArrayList<>(leftParts); + alignedRight = new ArrayList<>(rightParts); + + setView(new ViewAdjustParts(this, HandSide.LEFT, alignedLeft)); + getCurrentView().init(); + setListener(getCurrentView()); + + //make a copy of the parts + LinkedHashSet copyParts = new LinkedHashSet<>(); + for(Project.Part part : leftParts) + { + copyParts.add(part.clone()); + } + leftParts = copyParts; + + copyParts = new LinkedHashSet<>(); + for(Project.Part part : rightParts) + { + copyParts.add(part.clone()); + } + rightParts = copyParts; + } + } + else if(currentView instanceof ViewAdjustParts) + { + ViewAdjustParts view = (ViewAdjustParts)currentView; + if(view.handSide == HandSide.LEFT) + { + for(Project.Part leftPart : alignedLeft) + { + leftPart.showModel = false; + parent.mainframe.updatePart(leftPart, true); + } + + for(Project.Part rightPart : alignedRight) + { + rightPart.showModel = true; + parent.mainframe.updatePart(rightPart, true); + } + + setView(new ViewAdjustParts(this, HandSide.RIGHT, alignedRight)); + getCurrentView().init(); + setListener(getCurrentView()); + + //make a copy of the parts + LinkedHashSet copyParts = new LinkedHashSet<>(); + for(Project.Part part : rightParts) + { + copyParts.add(part.clone()); + } + + rightParts = copyParts; + } + else + { + for(Project.Part leftPart : alignedLeft) + { + leftPart.showModel = false; + parent.mainframe.updatePart(leftPart, true); + } + + if(!ExportList.EXPORTERS.get("handInfo").export(projectInfo.project, export())) + { + WindowPopup.popup(parent, 0.4D, 140, null, I18n.format("export.failed")); + } + else + { + WindowPopup.popup(parent, 0.3D, 140, null, I18n.format("gui.done")); + } + cancel(); + } + } + } + + public void cancel() + { + projectInfo.selectPart(null); + projectInfo.setGhostProject(null, 0.2F); + parent.removeWindow(this); + } + + public HandInfo export() + { + HandInfo info = new HandInfo(); + + String forClass = null; + + for(String note : projectInfo.project.notes) + { + if(note.startsWith("model-class:")) + { + forClass = note.substring("model-class:".length()); + break; + } + } + + if(forClass == null) + { + forClass = "Model Class Goes Here"; + } + + info.forClass = forClass; + + info.leftHandParts = new HandInfo.ModelRendererMarker[alignedLeft.size()]; + info.rightHandParts = new HandInfo.ModelRendererMarker[alignedRight.size()]; + + addMarkers(info.leftHandParts, alignedLeft, leftParts); + addMarkers(info.rightHandParts, alignedRight, rightParts); + + return info; + } + + public void addMarkers(HandInfo.ModelRendererMarker[] markers, ArrayList alignedParts, LinkedHashSet oriParts) + { + for(int i = 0; i < markers.length; i++) + { + HandInfo.ModelRendererMarker marker = new HandInfo.ModelRendererMarker(); + Project.Part aligned = alignedParts.get(i); + + marker.fieldName = aligned.name; + + Project.Part ori = null; + + for(Project.Part oriPart : oriParts) + { + if(aligned.name.equals(oriPart.name)) + { + ori = oriPart; + break; + } + } + + ArrayList placementCorrectors = new ArrayList<>(); + + //Reverse the rotationZYX by the model first, in XYZ order. + if(ori.rotAX != 0F) + { + PlacementCorrector corrector = new PlacementCorrector(); + corrector.type = "rotate"; + corrector.axis = "x"; + corrector.amount = (double)(-ori.rotAX); + placementCorrectors.add(corrector); + } + + if(ori.rotAY != 0F) + { + PlacementCorrector corrector = new PlacementCorrector(); + corrector.type = "rotate"; + corrector.axis = "y"; + corrector.amount = (double)(-ori.rotAY); + placementCorrectors.add(corrector); + } + + if(ori.rotAZ != 0F) + { + PlacementCorrector corrector = new PlacementCorrector(); + corrector.type = "rotate"; + corrector.axis = "z"; + corrector.amount = (double)(-ori.rotAZ); + placementCorrectors.add(corrector); + } + + //Translate to the right position + if(ori.rotPX != aligned.rotPX) + { + PlacementCorrector corrector = new PlacementCorrector(); + corrector.type = "translate"; + corrector.axis = "x"; + corrector.amount = (aligned.rotPX - ori.rotPX) / 16D; + placementCorrectors.add(corrector); + } + + if(ori.rotPY != aligned.rotPY) + { + PlacementCorrector corrector = new PlacementCorrector(); + corrector.type = "translate"; + corrector.axis = "y"; + corrector.amount = (aligned.rotPY - ori.rotPY) / 16D; + placementCorrectors.add(corrector); + } + + if(ori.rotPZ != aligned.rotPZ) + { + PlacementCorrector corrector = new PlacementCorrector(); + corrector.type = "translate"; + corrector.axis = "z"; + corrector.amount = (aligned.rotPZ - ori.rotPZ) / 16D; + placementCorrectors.add(corrector); + } + + if(aligned.rotAZ != 0D) + { + PlacementCorrector corrector = new PlacementCorrector(); + corrector.type = "rotate"; + corrector.axis = "z"; + corrector.amount = (double)(aligned.rotAZ); + placementCorrectors.add(corrector); + } + + if(aligned.rotAY != 0D) + { + PlacementCorrector corrector = new PlacementCorrector(); + corrector.type = "rotate"; + corrector.axis = "y"; + corrector.amount = (double)(aligned.rotAY); + placementCorrectors.add(corrector); + } + + if(aligned.rotAX != 0D) + { + PlacementCorrector corrector = new PlacementCorrector(); + corrector.type = "rotate"; + corrector.axis = "x"; + corrector.amount = (double)(aligned.rotAX); + placementCorrectors.add(corrector); + } + + placementCorrectors.removeIf(pc -> Math.abs(pc.amount) == 0.0D); //Remove -0.0s + + if(!placementCorrectors.isEmpty()) + { + marker.placementCorrectors = placementCorrectors.toArray(new PlacementCorrector[0]); + } + + markers[i] = marker; + } + } + + public static class ViewSelectParts extends View + { + public final HandSide handSide; + public final LinkedHashSet parts = new LinkedHashSet<>(); + + public ViewSelectParts(WindowExportHandInfo parent, HandSide side) + { + super(parent, ""); + + handSide = side; + + ElementButton button = new ElementButton<>(this, "gui.cancel", elementClickable -> + { + parent.cancel(); + }); + button.setId("btnCancel"); + button.setSize(60, 20); + button.setConstraint(new Constraint(button).bottom(this, Constraint.Property.Type.BOTTOM, 10).right(this, Constraint.Property.Type.RIGHT, 10)); + elements.add(button); + + ElementButton button1 = new ElementButton<>(this, "gui.ok", btn -> { + parent.nextStep(); + }); + button1.setId("btnOk"); + button1.setSize(60, 20); + button1.setConstraint(new Constraint(button1).right(button, Constraint.Property.Type.LEFT, 10)); + elements.add(button1); + + ElementTextWrapper text = new ElementTextWrapper(this); + text.setText(I18n.format(handSide == HandSide.LEFT ? "tabula.export.handInfo.pick.leftParts" : "tabula.export.handInfo.pick.rightParts")); + text.setId("text"); + text.constraints().left(this, Constraint.Property.Type.LEFT, 10).right(this, Constraint.Property.Type.RIGHT, 10).top(this, Constraint.Property.Type.TOP, 10); + elements.add(text); + } + + public void populateButtons() + { + elements.removeIf(element -> element.id == null); + + Element lastElement = getById("text"); + + for(Project.Part part : parts) + { + ElementButton btn = new ElementButton<>(this, "X", b -> { + if(parts.remove(part)) + { + parentFragment.projectInfo.selectPart(null); + populateButtons(); + } + }); + btn.setSize(16, 16); + btn.constraints().left(lastElement, Constraint.Property.Type.LEFT, 0).top(lastElement, Constraint.Property.Type.BOTTOM, 5); + elements.add(btn); + + ElementTextWrapper text = new ElementTextWrapper(this); + text.setText(part.name); + text.constraints().left(btn, Constraint.Property.Type.RIGHT, 6).top(btn, Constraint.Property.Type.TOP, 1).right(this, Constraint.Property.Type.RIGHT, 10); + elements.add(text); + + lastElement = btn; + } + + this.resize(getWorkspace().getMinecraft(), getWidth(), getHeight()); + } + + @Override + public void tick() + { + super.tick(); + + //Add selected parts + if(parentFragment.projectInfo.getSelectedPart() != null) + { + if(parts.add(parentFragment.projectInfo.getSelectedPart())) //successfully added + { + populateButtons(); + } + } + } + } + + public static class ViewAdjustParts extends View + { + public final HandSide handSide; + public final ArrayList parts; + + public Project.Part currentPart; + public int currentIndex = -1; + + public ViewAdjustParts(@Nonnull WindowExportHandInfo parent, HandSide side, ArrayList parts) + { + super(parent, ""); + this.handSide = side; + this.parts = parts; + + ElementButton button = new ElementButton<>(this, "gui.cancel", elementClickable -> + { + parent.cancel(); + }); + button.setId("btnCancel"); + button.setSize(60, 20); + button.setConstraint(new Constraint(button).bottom(this, Constraint.Property.Type.BOTTOM, 10).right(this, Constraint.Property.Type.RIGHT, 10)); + elements.add(button); + + ElementButton button1 = new ElementButton<>(this, "gui.ok", btn -> { + currentIndex++; + if(currentIndex < parts.size()) + { + populatePart(); + } + else + { + parent.nextStep(); + } + }); + button1.setId("btnOk"); + button1.setSize(60, 20); + button1.setConstraint(new Constraint(button1).right(button, Constraint.Property.Type.LEFT, 10)); + elements.add(button1); + + ElementTextWrapper text = new ElementTextWrapper(this); + text.setText(I18n.format(handSide == HandSide.LEFT ? "tabula.export.handInfo.set.leftParts" : "tabula.export.handInfo.set.rightParts")); + text.setId("text"); + text.constraints().left(this, Constraint.Property.Type.LEFT, 10).right(this, Constraint.Property.Type.RIGHT, 10).top(this, Constraint.Property.Type.TOP, 10); + elements.add(text); + + //Elements + int numberInputWidth = 45; + Consumer responder = s -> { + if(!s.isEmpty()) + { + updatePart(); + } + }; + Consumer enterResponder = s -> updatePart(); //bypass the empty check + + ElementTextWrapper text1 = new ElementTextWrapper(this); + text1.setNoWrap().setText(I18n.format("window.controls.position")); + text1.constraints().left(text, Constraint.Property.Type.LEFT, 0).top(text, Constraint.Property.Type.BOTTOM, 10); + elements.add(text1); + + ElementSharedSpace space = new ElementSharedSpace(this, ElementScrollBar.Orientation.HORIZONTAL); + space.setSize(14, 14).constraints().left(text1, Constraint.Property.Type.LEFT, 0).top(text1, Constraint.Property.Type.BOTTOM, 2).right(text, Constraint.Property.Type.RIGHT, 0); + elements.add(space); + + ElementNumberInput num = new ElementNumberInput(space, true); + num.setMaxDec(Tabula.configClient.guiMaxDecimals).setSize(numberInputWidth, 14).setId("posX"); + num.setResponder(responder).setEnterResponder(enterResponder); + num.constraints().left(space, Constraint.Property.Type.LEFT, 0).top(space, Constraint.Property.Type.TOP, 0); + space.addElement(num); + + ElementNumberInput num1 = new ElementNumberInput(space, true); + num1.setMaxDec(Tabula.configClient.guiMaxDecimals).setSize(numberInputWidth, 14).setId("posY"); + num1.setResponder(responder).setEnterResponder(enterResponder); + num1.constraints().left(num, Constraint.Property.Type.RIGHT, 0).top(space, Constraint.Property.Type.TOP, 0); + space.addElement(num1); + + ElementNumberInput num2 = new ElementNumberInput(space, true); + num2.setMaxDec(Tabula.configClient.guiMaxDecimals).setSize(numberInputWidth, 14).setId("posZ"); + num2.setResponder(responder).setEnterResponder(enterResponder); + num2.constraints().left(num1, Constraint.Property.Type.RIGHT, 0).top(space, Constraint.Property.Type.TOP, 0).right(space, Constraint.Property.Type.RIGHT, 0); + space.addElement(num2); + + ElementTextWrapper text2 = new ElementTextWrapper(this); + text2.setNoWrap().setText(I18n.format("window.controls.rotation")); + text2.constraints().left(text, Constraint.Property.Type.LEFT, 0).top(num, Constraint.Property.Type.BOTTOM, 5); + elements.add(text2); + + space = new ElementSharedSpace(this, ElementScrollBar.Orientation.HORIZONTAL); + space.setSize(14, 14).constraints().left(text2, Constraint.Property.Type.LEFT, 0).top(text2, Constraint.Property.Type.BOTTOM, 2).right(text, Constraint.Property.Type.RIGHT, 0); + elements.add(space); + + num = new ElementNumberInput(space, true); + num.setMaxDec(Tabula.configClient.guiMaxDecimals).setMin(-180).setMax(180).setSize(numberInputWidth, 14).setId("rotX"); + num.setResponder(responder).setEnterResponder(enterResponder); + num.setConstraint(new Constraint(num).left(space, Constraint.Property.Type.LEFT, 0).top(space, Constraint.Property.Type.TOP, 0)); + space.addElement(num); + + num1 = new ElementNumberInput(space, true); + num1.setMaxDec(Tabula.configClient.guiMaxDecimals).setMin(-180).setMax(180).setSize(numberInputWidth, 14).setId("rotY"); + num1.setResponder(responder).setEnterResponder(enterResponder); + num1.setConstraint(new Constraint(num1).left(num, Constraint.Property.Type.RIGHT, 0).top(space, Constraint.Property.Type.TOP, 0)); + space.addElement(num1); + + num2 = new ElementNumberInput(space, true); + num2.setMaxDec(Tabula.configClient.guiMaxDecimals).setMin(-180).setMax(180).setSize(numberInputWidth, 14).setId("rotZ"); + num2.setResponder(responder).setEnterResponder(enterResponder); + num2.setConstraint(new Constraint(num2).left(num1, Constraint.Property.Type.RIGHT, 0).top(space, Constraint.Property.Type.TOP, 0).right(space, Constraint.Property.Type.RIGHT, 0)); + space.addElement(num2); + } + + private void updatePart() + { + if(currentPart != null) + { + String preUpdate = currentPart.getJsonWithoutChildren(); + + currentPart.rotPX = (float)((ElementNumberInput)getById("posX")).getDouble(); + currentPart.rotPY = (float)((ElementNumberInput)getById("posY")).getDouble(); + currentPart.rotPZ = (float)((ElementNumberInput)getById("posZ")).getDouble(); + + currentPart.rotAX = (float)((ElementNumberInput)getById("rotX")).getDouble(); + currentPart.rotAY = (float)((ElementNumberInput)getById("rotY")).getDouble(); + currentPart.rotAZ = (float)((ElementNumberInput)getById("rotZ")).getDouble(); + + String postUpdate = currentPart.getJsonWithoutChildren(); + if(!postUpdate.equals(preUpdate)) + { + parentFragment.parent.mainframe.updatePart(currentPart, true); + } + } + } + + public void populatePart() + { + if(currentIndex < parts.size()) + { + currentPart = null; + + Project.Part part = parts.get(currentIndex); + + ((ElementNumberInput)getById("posX")).setText(String.format(Locale.ENGLISH, "%." + Tabula.configClient.guiMaxDecimals + "f", part.rotPX)); + ((ElementNumberInput)getById("posY")).setText(String.format(Locale.ENGLISH, "%." + Tabula.configClient.guiMaxDecimals + "f", part.rotPY)); + ((ElementNumberInput)getById("posZ")).setText(String.format(Locale.ENGLISH, "%." + Tabula.configClient.guiMaxDecimals + "f", part.rotPZ)); + + ((ElementNumberInput)getById("rotX")).setText(String.format(Locale.ENGLISH, "%." + Tabula.configClient.guiMaxDecimals + "f", part.rotAX)); + ((ElementNumberInput)getById("rotY")).setText(String.format(Locale.ENGLISH, "%." + Tabula.configClient.guiMaxDecimals + "f", part.rotAY)); + ((ElementNumberInput)getById("rotZ")).setText(String.format(Locale.ENGLISH, "%." + Tabula.configClient.guiMaxDecimals + "f", part.rotAZ)); + + currentPart = part; + + parentFragment.projectInfo.selectPart(currentPart); + } + } + + @Override + public void tick() + { + super.tick(); + + if(currentIndex == -1) + { + currentIndex++; + populatePart(); + } + } + } +} diff --git a/src/main/java/me/ichun/mods/tabula/client/gui/window/popup/WindowExportHeadInfo.java b/src/main/java/me/ichun/mods/tabula/client/gui/window/popup/WindowExportHeadInfo.java index e7c5a5b..2d89a79 100644 --- a/src/main/java/me/ichun/mods/tabula/client/gui/window/popup/WindowExportHeadInfo.java +++ b/src/main/java/me/ichun/mods/tabula/client/gui/window/popup/WindowExportHeadInfo.java @@ -18,7 +18,10 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Locale; import java.util.function.Consumer; public class WindowExportHeadInfo extends Window diff --git a/src/main/java/me/ichun/mods/tabula/client/gui/window/popup/WindowImportMCProject.java b/src/main/java/me/ichun/mods/tabula/client/gui/window/popup/WindowImportMCProject.java index 69bd833..162d11a 100644 --- a/src/main/java/me/ichun/mods/tabula/client/gui/window/popup/WindowImportMCProject.java +++ b/src/main/java/me/ichun/mods/tabula/client/gui/window/popup/WindowImportMCProject.java @@ -742,6 +742,7 @@ public void loadModel(ModelInfo model) { project.notes.add("suspected-origin-entity:" + model.originEntity.getName()); } + project.notes.add("model-class:" + model.model.getClass().getName()); if(texture && model.texture != null) { try diff --git a/src/main/resources/PlayerGhost.tbl b/src/main/resources/PlayerGhost.tbl new file mode 100644 index 0000000000000000000000000000000000000000..bdb499f1f722c716457a301f59955192e024a621 GIT binary patch literal 3185 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