package com.akjava.gwt.bvhtools.client.tools;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.akjava.bvh.client.BVH;
import com.akjava.bvh.client.BVHMotion;
import com.akjava.bvh.client.BVHNode;
import com.akjava.bvh.client.BVHParser;
import com.akjava.bvh.client.BVHParser.InvalidLineException;
import com.akjava.bvh.client.BVHWriter;
import com.akjava.bvh.client.NameAndChannel;
import com.akjava.gwt.html5.client.file.File;
import com.akjava.gwt.html5.client.file.FileHandler;
import com.akjava.gwt.html5.client.file.FileReader;
import com.akjava.gwt.html5.client.file.FileUploadForm;
import com.akjava.gwt.html5.client.file.FileUtils;
import com.akjava.gwt.lib.client.LogUtils;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FileUpload;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.VerticalPanel;
public class MixTool extends AbstractTool{
private File firstFile,secondFile;
private CheckBox loopShort;
public MixTool(VerticalPanel panel){
super(panel);
final FileUploadForm upload=new FileUploadForm();
upload.getFileUpload().getElement().setAttribute("multiple", "multiple");
upload.getFileUpload().addChangeHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent event) {
JsArray<File> files=FileUtils.toFile(event.getNativeEvent());
setFile(files,true);
upload.reset();
}
});
panel.add(upload);
final FileUploadForm upload2=new FileUploadForm();
//upload.getElement().setAttribute("multiple", "multiple");
upload2.getFileUpload().addChangeHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent event) {
JsArray<File> files=FileUtils.toFile(event.getNativeEvent());
setFile(files,false);
upload2.reset();
}
});
panel.add(upload2);
HorizontalPanel labels=new HorizontalPanel();
panel.add(labels);
firstFileName=new Label();
firstFileName.setWidth("200px");
labels.add(firstFileName);
secondFileName=new Label();
secondFileName.setWidth("200px");
labels.add(secondFileName);
keepShort = new CheckBox("max frame is same as shorter one");
keepShort.setValue(true);
panel.add(keepShort);
loopShort = new CheckBox("loop shorter one");
loopShort.setValue(true);
panel.add(loopShort);
panel.add(new Label("Use BVH1 checks"));
ScrollPanel scroll=new ScrollPanel();
scroll.setSize("400px", "200px");
boneCheckPanel=new VerticalPanel();
scroll.setWidget(boneCheckPanel);
panel.add(scroll);
mixButton = new Button("Mix");
mixButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
doMix();
}
});
mixButton.setVisible(false);
panel.add(mixButton);
warnLabel = new Label("Error.bvh1 and bvh2 must have same bones");
panel.add(warnLabel);
warnLabel.setVisible(false);
HorizontalPanel buttons=new HorizontalPanel();
panel.add(buttons);
buttons.setHorizontalAlignment(HorizontalPanel.ALIGN_RIGHT);
buttons.setWidth("400px");
Button selectAll=new Button("Select Text");
buttons.add(selectAll);
textArea = new TextArea();
textArea.setSize("400px", "100px");
textArea.setReadOnly(true);
//textArea.setStylePrimaryName("nowrap"); ,wrap replace some char and make a problem
panel.add(textArea);
selectAll.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
textArea.selectAll();
}
});
panel.add(createPlayButton("MixedData", textArea));
}
private Map<String,Boolean> useMap=new HashMap<String,Boolean>();
VerticalPanel boneCheckPanel;
protected void doMix() {
BVH bvh1=bvhs.get(0);
BVH bvh2=bvhs.get(1);
BVH result=new BVH();
result.setHiearchy(bvh1.getHiearchy());
BVHMotion motion=new BVHMotion();
motion.setFrameTime(bvh1.getFrameTime());
result.setMotion(motion);
int length=bvh1.getFrames();
if(bvh2.getFrames()>length){
if(!keepShort.getValue()){
length=bvh2.getFrames();
}
}else{
if(keepShort.getValue()){
length=bvh2.getFrames();
}
}
List<NameAndChannel> channel=bvh1.getNameAndChannels();
for(int i=0;i<length;i++){
double[] value1;
double[] value2;
if(i<bvh1.getFrames()){
value1=bvh1.getFrameAt(i);
}else{
if(loopShort.getValue() && bvh1.getFrames()>1){
int f=(i-bvh1.getFrames())%(bvh1.getFrames()-1);//skip first;
value1=bvh1.getFrameAt(f+1);
}else{
value1=new double[channel.size()];
}
}
if(i<bvh2.getFrames()){
value2=bvh2.getFrameAt(i);
}else{
if(loopShort.getValue() && bvh2.getFrames()>1){
int f=(i-bvh2.getFrames())%(bvh2.getFrames()-1);//skip first;
value2=bvh2.getFrameAt(f+1);
}else{
value2=new double[channel.size()];
}
}
double[] values=new double[channel.size()];
for(int j=0;j<channel.size();j++){
String name=channel.get(j).getName();
if(useMap.get(name)){
values[j]=value1[j];
}else{
values[j]=value2[j];
}
}
motion.add(values);
}
motion.syncFrames();
BVHWriter writer=new BVHWriter();
String text=writer.writeToString(result);
textArea.setText(text);
}
private TextArea textArea;
private CheckBox keepShort;
private void parseBVH(String bvhText){
BVHParser parser=new BVHParser();
try {
BVH bvh=parser.parse(bvhText);
bvhs.add(bvh);
} catch (InvalidLineException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void setFile(JsArray<File> files,boolean isFirst){
LogUtils.log("file-size:"+files.length());
if(isFirst){
firstFile=files.get(0);
if(files.length()>1){
secondFile=files.get(1);
}
}else{
secondFile=files.get(0);
}
updateLabel();
if(firstFile!=null && secondFile!=null){
loadFiles();
}
}
private void updateLabel(){
if(firstFile!=null){
firstFileName.setText(firstFile.getFileName());
}
if(secondFile!=null){
secondFileName.setText(secondFile.getFileName());
}
}
private Label firstFileName,secondFileName;
private List<BVH> bvhs;
private Label warnLabel;
private Button mixButton;
private void loadFiles(){
bvhs=new ArrayList<BVH>();
final List<File> files=new ArrayList<File>();
files.add(firstFile);
files.add(secondFile);
final FileReader reader=FileReader.createFileReader();
reader.setOnLoad(new FileHandler() {
@Override
public void onLoad() {
parseBVH(reader.getResultAsString());
if(files.size()>0){
File f=files.remove(0);
reader.readAsText(f,"utf-8");
}else{//last
doAllFileAction();
}
}
});
reader.readAsText(files.remove(0),"utf-8");
}
protected void doAllFileAction() {
//doStrip();
//check same and
boolean same=isSameNode(bvhs.get(0), bvhs.get(1));
if(!same){
warnLabel.setVisible(true);
mixButton.setVisible(false);
}else{
warnLabel.setVisible(false);
mixButton.setVisible(true);
}
useMap.clear();
//create check
boneCheckPanel.clear();
BVH bvh=bvhs.get(0);
for(BVHNode node:bvh.getNodeList()){
final CheckBox check=new CheckBox();
check.setText(node.getName());
check.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if(check.getValue()){
useMap.put(check.getText(), true);
}else{
useMap.put(check.getText(), false);
}
}
});
check.setValue(true);
useMap.put(node.getName(), true);
boneCheckPanel.add(check);
}
}
public static boolean isSameNode(BVH bvh1,BVH bvh2){
boolean same=true;
List<BVHNode> node1=bvh1.getNodeList();
List<BVHNode> node2=bvh2.getNodeList();
if(node1.size()!=node2.size()){
return false;
}
for(int i=0;i<node1.size();i++){
if(!node1.get(i).getName().equals(node1.get(i).getName())){
return false;
}
}
return same;
}
}