Renderer/src/main/java/electrosphere/renderer/ui/components/CharacterCustomizer.java
austin 63feb835cd
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
slider fixes, dragevent fixes, new component
2024-09-15 22:49:28 -04:00

161 lines
7.4 KiB
Java

package electrosphere.renderer.ui.components;
import java.util.stream.Collectors;
import org.joml.Vector3f;
import electrosphere.client.entity.camera.CameraEntityUtils;
import electrosphere.engine.Globals;
import electrosphere.entity.types.creature.CreatureTemplate;
import electrosphere.game.data.creature.type.CreatureData;
import electrosphere.game.data.creature.type.visualattribute.AttributeVariant;
import electrosphere.game.data.creature.type.visualattribute.VisualAttribute;
import electrosphere.net.parser.net.message.CharacterMessage;
import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.actor.ActorStaticMorph;
import electrosphere.renderer.actor.ActorUtils;
import electrosphere.renderer.ui.elements.ActorPanel;
import electrosphere.renderer.ui.elements.Button;
import electrosphere.renderer.ui.elements.Div;
import electrosphere.renderer.ui.elements.Label;
import electrosphere.renderer.ui.elements.ScrollableContainer;
import electrosphere.renderer.ui.elements.Slider;
import electrosphere.renderer.ui.elements.StringCarousel;
import electrosphere.renderer.ui.elementtypes.Element;
import electrosphere.renderer.ui.events.ValueChangeEvent;
import electrosphere.util.Utilities;
/**
* Panel to customize a character
*/
public class CharacterCustomizer {
/**
* Minimum width of the component
*/
public static final int MIN_WIDTH = 500;
/**
* Minimum height of the component
*/
public static final int MIN_HEIGHT = 500;
/**
* Creates a character customizer panel
* @param race The race of the character
* @return The panel component
*/
public static Element createCharacterCustomizerPanel(String race){
//figure out race data
CreatureData selectedRaceType = Globals.gameConfigCurrent.getCreatureTypeLoader().getType(race);
//spawn camera so renderer doesn't crash (once render pipeline is modularized this shouldn't be necessary)
Globals.playerCamera = CameraEntityUtils.spawnBasicCameraEntity(new Vector3f(0,0,0), new Vector3f(0,0.3f,1).normalize());
Globals.viewMatrix = CameraEntityUtils.getCameraViewMatrix(Globals.playerCamera);
//create actor panel
Actor characterActor = ActorUtils.createActorFromModelPath(selectedRaceType.getModelPath());
ActorPanel actorPanel = ActorPanel.create(characterActor);
actorPanel.setAnimation(selectedRaceType.getIdleData().getAnimation().getNameThirdPerson());
actorPanel.setPosition(new Vector3f(0,-0.5f,-0.6f));
actorPanel.setScale(new Vector3f(1.0f));
//have to build static morph while looping through attributes
ActorStaticMorph staticMorph = new ActorStaticMorph();
//create creature template
CreatureTemplate template = CreatureTemplate.create(race);
//create scrollable
ScrollableContainer scrollable = ScrollableContainer.createScrollable();
scrollable.setMinWidth(MIN_WIDTH);
scrollable.setMinHeight(MIN_HEIGHT);
//create edit controls here
for(VisualAttribute attribute : selectedRaceType.getVisualAttributes()){
if(attribute.getType().equals(VisualAttribute.TYPE_BONE)){
//add label for slider
Label sliderName = new Label(0.6f);
sliderName.setText(attribute.getAttributeId());
sliderName.setMinWidth(200);
//add a slider
Slider boneSlider = Slider.createSlider((ValueChangeEvent event) -> {
if(characterActor.getStaticMorph() != null){
staticMorph.updateValue(attribute.getSubtype(), attribute.getPrimaryBone(), event.getAsFloat());
if(attribute.getMirrorBone() != null){
staticMorph.updateValue(attribute.getSubtype(), attribute.getMirrorBone(), event.getAsFloat());
}
template.getAttributeValue(attribute.getAttributeId()).setValue(event.getAsFloat());
}
});
float min = attribute.getMinValue();
float max = attribute.getMaxValue();
float defaultValue = min + (max - min)/2.0f;
boneSlider.setMinimum(min);
boneSlider.setMaximum(max);
boneSlider.setValue(defaultValue);
boneSlider.setMinWidth(200);
//actually add attributes to static morph
if(attribute.getPrimaryBone() != null && staticMorph.getBoneTransforms(attribute.getPrimaryBone()) == null){
staticMorph.initBoneTransforms(attribute.getPrimaryBone());
}
if(attribute.getMirrorBone() != null && staticMorph.getBoneTransforms(attribute.getMirrorBone()) == null){
staticMorph.initBoneTransforms(attribute.getMirrorBone());
}
//add attribute to creature template
template.putAttributeValue(attribute.getAttributeId(), defaultValue);
scrollable.addChild(Div.createRow(sliderName,boneSlider));
} else if(attribute.getType().equals(VisualAttribute.TYPE_REMESH)){
//add label for carousel
Label scrollableName = new Label(0.6f);
scrollableName.setText(attribute.getAttributeId());
scrollableName.setMinWidth(200);
//add a carousel
StringCarousel variantCarousel = StringCarousel.create(
// attribute.getVariants().stream().filter(variant -> ),
attribute.getVariants().stream().map(variant -> variant.getId()).collect(Collectors.toList()),
(ValueChangeEvent event) -> {
//TODO: implement updating visuals
template.getAttributeValue(attribute.getAttributeId()).setVariantId(event.getAsString());
AttributeVariant variant = null;
for(AttributeVariant variantCurrent : attribute.getVariants()){
if(variantCurrent.getId().equals(event.getAsString())){
variant = variantCurrent;
break;
}
}
if(variant != null){
Globals.assetManager.addModelPathToQueue(variant.getModel());
for(String mesh : variant.getMeshes()){
characterActor.getMeshMask().queueMesh(variant.getModel(), mesh);
}
}
}
);
variantCarousel.setMinWidth(200);
//set the current attrib for the template
template.putAttributeValue(attribute.getAttributeId(), attribute.getVariants().get(0).getId());
scrollable.addChild(Div.createRow(scrollableName,variantCarousel));
}
}
//finally set static morph
characterActor.setActorStaticMorph(staticMorph);
//create layout
Div rVal = Div.createCol(
Div.createRow(
scrollable,
actorPanel
),
Button.createButton("Create", () -> {
Globals.clientConnection.queueOutgoingMessage(CharacterMessage.constructRequestCreateCharacterMessage(Utilities.stringify(template)));
})
);
return rVal;
}
}