Basic character editor ui functional

This commit is contained in:
austin 2022-05-03 16:36:57 -04:00
parent 303aaf3740
commit ab41020e1c
5 changed files with 337 additions and 69 deletions

View File

@ -68,6 +68,14 @@
"primaryBone" : "UpperTorso",
"minValue" : -0.2,
"maxValue" : 0.2
},
{
"attributeId" : "HeadWidth",
"type" : "bone",
"subtype" : "scalex",
"primaryBone" : "Head",
"minValue" : 0.8,
"maxValue" : 1.2
}
],
"movementSystems" : [

View File

@ -785,64 +785,9 @@ public class MenuGenerators {
float minVal = attribute.getMinValue();
float range = attribute.getMaxValue() - minVal;
float actualValue = minVal + range * value;
switch(attribute.getSubtype()){
case "yaw":
staticMorph.setYaw(attribute.getPrimaryBone(), actualValue);
if(attribute.getMirrorBone() != null){
staticMorph.setYaw(attribute.getMirrorBone(), -actualValue);
}
break;
case "pitch":
staticMorph.setPitch(attribute.getPrimaryBone(), actualValue);
if(attribute.getMirrorBone() != null){
staticMorph.setPitch(attribute.getMirrorBone(), -actualValue);
}
break;
case "roll":
staticMorph.setRoll(attribute.getPrimaryBone(), actualValue);
if(attribute.getMirrorBone() != null){
staticMorph.setRoll(attribute.getMirrorBone(), -actualValue);
}
break;
case "scalex":
staticMorph.setScaleX(attribute.getPrimaryBone(), actualValue);
if(attribute.getMirrorBone() != null){
staticMorph.setScaleX(attribute.getMirrorBone(), -actualValue);
}
break;
case "scaley":
staticMorph.setScaleY(attribute.getPrimaryBone(), actualValue);
if(attribute.getMirrorBone() != null){
staticMorph.setScaleY(attribute.getMirrorBone(), -actualValue);
}
break;
case "scalez":
staticMorph.setScaleZ(attribute.getPrimaryBone(), actualValue);
if(attribute.getMirrorBone() != null){
staticMorph.setScaleZ(attribute.getMirrorBone(), -actualValue);
}
break;
case "offx":
staticMorph.setOffsetX(attribute.getPrimaryBone(), actualValue);
if(attribute.getMirrorBone() != null){
staticMorph.setOffsetX(attribute.getMirrorBone(), -actualValue);
}
break;
case "offy":
staticMorph.setOffsetY(attribute.getPrimaryBone(), actualValue);
if(attribute.getMirrorBone() != null){
staticMorph.setOffsetY(attribute.getMirrorBone(), -actualValue);
}
break;
case "offz":
staticMorph.setOffsetZ(attribute.getPrimaryBone(), actualValue);
if(attribute.getMirrorBone() != null){
staticMorph.setOffsetZ(attribute.getMirrorBone(), -actualValue);
}
break;
case "offl":
//TODO
break;
staticMorph.updateValue(attribute.getSubtype(), attribute.getPrimaryBone(), event.getAsFloat());
if(attribute.getMirrorBone() != null){
staticMorph.updateValue(attribute.getSubtype(), attribute.getMirrorBone(), event.getAsFloat());
}
}});
scrollable.addChild(attributeSlider);

View File

@ -3,15 +3,24 @@ package electrosphere.menu;
import java.util.LinkedList;
import java.util.List;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import electrosphere.entity.types.camera.CameraEntityUtils;
import electrosphere.game.data.creature.type.CreatureType;
import electrosphere.game.data.creature.type.visualattribute.AttributeVariant;
import electrosphere.game.data.creature.type.visualattribute.VisualAttribute;
import electrosphere.main.Globals;
import electrosphere.renderer.Camera;
import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.actor.ActorStaticMorph;
import electrosphere.renderer.actor.ActorUtils;
import electrosphere.renderer.actor.ActorStaticMorph.StaticMorphTransforms;
import electrosphere.renderer.anim.Animation;
import electrosphere.renderer.ui.ClickableElement;
import electrosphere.renderer.ui.Element;
import electrosphere.renderer.ui.ValueElement.ValueChangeEventCallback;
import electrosphere.renderer.ui.elements.ActorPanel;
import electrosphere.renderer.ui.elements.Button;
import electrosphere.renderer.ui.elements.ImagePanel;
import electrosphere.renderer.ui.elements.Label;
@ -78,9 +87,25 @@ public class MenuGeneratorsMultiplayer {
int verticalPosition = 125;
int horizontalPosition = 300;
//figure out race data
CreatureType selectedRaceType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(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(-1,0.2f,0).normalize());
//create actor panel
Actor characterActor = ActorUtils.createActorFromModelPath(selectedRaceType.getModelPath());
ActorPanel actorPanel = new ActorPanel(1200, 100, 500, 500, characterActor);
actorPanel.setAnimation(Animation.ANIMATION_IDLE_1);
actorPanel.setPosition(new Vector3f(-5,-2,0));
actorPanel.setRotation(new Quaternionf().rotateLocalY((float)(Math.PI/4.0)));
actorPanel.setScale(new Vector3f(0.03f,0.03f,0.03f));
//have to build static morph while looping through attributes
ActorStaticMorph staticMorph = new ActorStaticMorph();
List<Element> controlsToAdd = new LinkedList<Element>();
//create edit controls here
CreatureType selectedRaceType = Globals.gameConfigCurrent.getCreatureTypeLoader().getCreature(race);
for(VisualAttribute attribute : selectedRaceType.getVisualAttributes()){
if(attribute.getType().equals(VisualAttribute.TYPE_BONE)){
//add label for slider
@ -95,6 +120,23 @@ public class MenuGeneratorsMultiplayer {
boneSlider.setMaximum(max);
boneSlider.setValue(min + (max - min)/2.0f);
controlsToAdd.add(boneSlider);
//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());
}
//set callback for when we change the slider value to update the static morph
boneSlider.setOnValueChangeCallback(new ValueChangeEventCallback() {public void execute(ValueChangeEvent event) {
if(characterActor.getStaticMorph() != null){
ActorStaticMorph staticMorph = characterActor.getStaticMorph();
staticMorph.updateValue(attribute.getSubtype(), attribute.getPrimaryBone(), event.getAsFloat());
if(attribute.getMirrorBone() != null){
staticMorph.updateValue(attribute.getSubtype(), attribute.getMirrorBone(), -event.getAsFloat());
}
}
}});
} else if(attribute.getType().equals(VisualAttribute.TYPE_REMESH)){
//add label for carousel
Label sliderName = new Label(20, verticalPosition, 0.6f);
@ -109,6 +151,8 @@ public class MenuGeneratorsMultiplayer {
}
verticalPosition = verticalPosition + 100;
}
//finally set static morph
characterActor.setActorStaticMorph(staticMorph);
//add button to actually create the character
Button createCharacterButton = new Button();
@ -121,13 +165,16 @@ public class MenuGeneratorsMultiplayer {
return false;
}});
int width = 1000;
int width = 1800;
int height = verticalPosition + 300;
ScrollableContainer scrollable = new ScrollableContainer(0, 0, width, height);
for(Element newControl : controlsToAdd){
scrollable.addChild(newControl);
}
scrollable.addChild(actorPanel);
// rVal.addChild(scrollable);
// Label testLabel = new Label(100,215,1.0f);

View File

@ -19,60 +19,98 @@ public class ActorStaticMorph {
return boneTransformMap.get(boneName);
}
public void setYaw(String boneName, float yaw){
void setYaw(String boneName, float yaw){
if(boneTransformMap.containsKey(boneName)){
boneTransformMap.get(boneName).yaw = yaw;
}
}
public void setPitch(String boneName, float pitch){
void setPitch(String boneName, float pitch){
if(boneTransformMap.containsKey(boneName)){
boneTransformMap.get(boneName).pitch = pitch;
}
}
public void setRoll(String boneName, float roll){
void setRoll(String boneName, float roll){
if(boneTransformMap.containsKey(boneName)){
boneTransformMap.get(boneName).roll = roll;
}
}
public void setOffsetX(String boneName, float offsetX){
void setOffsetX(String boneName, float offsetX){
if(boneTransformMap.containsKey(boneName)){
boneTransformMap.get(boneName).offset.x = offsetX;
}
}
public void setOffsetY(String boneName, float offsetY){
void setOffsetY(String boneName, float offsetY){
if(boneTransformMap.containsKey(boneName)){
boneTransformMap.get(boneName).offset.y = offsetY;
}
}
public void setOffsetZ(String boneName, float offsetZ){
void setOffsetZ(String boneName, float offsetZ){
if(boneTransformMap.containsKey(boneName)){
boneTransformMap.get(boneName).offset.z = offsetZ;
}
}
public void setScaleX(String boneName, float scaleX){
void setScaleX(String boneName, float scaleX){
if(boneTransformMap.containsKey(boneName)){
boneTransformMap.get(boneName).scale.x = scaleX;
}
}
public void setScaleY(String boneName, float scaleY){
void setScaleY(String boneName, float scaleY){
if(boneTransformMap.containsKey(boneName)){
boneTransformMap.get(boneName).scale.y = scaleY;
}
}
public void setScaleZ(String boneName, float scaleZ){
void setScaleZ(String boneName, float scaleZ){
if(boneTransformMap.containsKey(boneName)){
boneTransformMap.get(boneName).scale.z = scaleZ;
}
}
/**
* Instead of having this code be duplicated every time we want to update a static morph, putting it in here
*/
public void updateValue(String subtype, String bone, float value){
switch(subtype){
case "yaw":
this.setYaw(bone, value);
break;
case "pitch":
this.setPitch(bone, value);
break;
case "roll":
this.setRoll(bone, value);
break;
case "scalex":
this.setScaleX(bone, value);
break;
case "scaley":
this.setScaleY(bone, value);
break;
case "scalez":
this.setScaleZ(bone, value);
break;
case "offx":
this.setOffsetX(bone, value);
break;
case "offy":
this.setOffsetY(bone, value);
break;
case "offz":
this.setOffsetZ(bone, value);
break;
case "offl":
//TODO
break;
}
}
public class StaticMorphTransforms {

View File

@ -0,0 +1,230 @@
package electrosphere.renderer.ui.elements;
import org.joml.Matrix4f;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glClearColor;
import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER;
import static org.lwjgl.opengl.GL30.glBindFramebuffer;
import electrosphere.logger.LoggerInterface;
import electrosphere.main.Globals;
import electrosphere.main.Main;
import electrosphere.renderer.Material;
import electrosphere.renderer.Model;
import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.framebuffer.Framebuffer;
import electrosphere.renderer.framebuffer.FramebufferUtils;
import electrosphere.renderer.texture.Texture;
import electrosphere.renderer.ui.DraggableElement;
import electrosphere.renderer.ui.DrawableElement;
import electrosphere.renderer.ui.events.DragEvent;
import electrosphere.renderer.ui.events.Event;
import electrosphere.renderer.ui.events.DragEvent.DragEventType;
public class ActorPanel implements DrawableElement, DraggableElement {
Material customMat = new Material();
Framebuffer elementBuffer;
Actor actor;
Matrix4f modelMatrix = new Matrix4f();
String currentAnim;
Vector3f actorPosition = new Vector3f(0,0,0);
Quaternionf actorRotation = new Quaternionf();
Vector3f actorScale = new Vector3f(1,1,1);
Vector3f texPosition = new Vector3f(0,0,0);
Vector3f texScale = new Vector3f(1,1,0);
DragEventCallback onDragStart;
DragEventCallback onDrag;
DragEventCallback onDragRelease;
public ActorPanel(int x, int y, int width, int height, Actor actor){
elementBuffer = FramebufferUtils.generateTextureFramebuffer(width, height);
customMat.setTexturePointer(elementBuffer.getTexturePointer());
this.actor = actor;
this.positionX = x;
this.positionY = y;
this.width = width;
this.height = height;
recalculateModelMatrix();
}
@Override
public void draw(int parentFramebufferPointer, int parentWidth, int parentHeight) {
elementBuffer.bind();
// Globals.renderingEngine.setViewportSize(width, height);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if(currentAnim != null){
if(!actor.isPlayingAnimation() || !actor.isPlayingAnimation(currentAnim)){
actor.playAnimation(currentAnim,3);
actor.incrementAnimationTime(Main.deltaFrames);
}
}
actor.applyModelMatrix(modelMatrix);
actor.draw(true);
//this call binds the screen as the "texture" we're rendering to
//have to call before actually rendering
glBindFramebuffer(GL_FRAMEBUFFER, parentFramebufferPointer);
float ndcX = (float)positionX/parentWidth;
float ndcY = (float)positionY/parentHeight;
float ndcWidth = (float)width/parentWidth;
float ndcHeight = (float)height/parentHeight;
Vector3f boxPosition = new Vector3f(ndcX,ndcY,0);
Vector3f boxDimensions = new Vector3f(ndcWidth,ndcHeight,0);
Model planeModel = Globals.assetManager.fetchModel(ImagePanel.imagePanelModelPath);
if(planeModel != null){
planeModel.pushUniformToMesh("plane", "mPosition", boxPosition);
planeModel.pushUniformToMesh("plane", "mDimension", boxDimensions);
planeModel.pushUniformToMesh("plane", "tPosition", texPosition);
planeModel.pushUniformToMesh("plane", "tDimension", texScale);
planeModel.meshes.get(0).setMaterial(customMat);
planeModel.drawUI();
} else {
LoggerInterface.loggerRenderer.ERROR("Actor Panel unable to find plane model!!", new Exception());
}
}
public int width = 1;
public int height = 1;
public int positionX = 0;
public int positionY = 0;
public int parentWidth = 1;
public int parentHeight = 1;
public boolean visible = false;
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public int getPositionX() {
return positionX;
}
public int getPositionY() {
return positionY;
}
public boolean getVisible() {
return visible;
}
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public void setPositionX(int positionX) {
this.positionX = positionX;
}
public void setPositionY(int positionY) {
this.positionY = positionY;
}
public void setVisible(boolean draw) {
this.visible = draw;
}
public void setParentWidth(int width){
parentWidth = width;
}
public void setParentHeight(int height){
this.parentHeight = height;
}
public void setAnimation(String animation){
currentAnim = animation;
}
public void setPosition(Vector3f position){
this.actorPosition.set(position);
recalculateModelMatrix();
}
public void setRotation(Quaternionf rotation){
this.actorRotation.set(rotation);
recalculateModelMatrix();
}
public void setScale(Vector3f scale){
this.actorScale.set(scale);
recalculateModelMatrix();
}
void recalculateModelMatrix(){
modelMatrix.identity();
modelMatrix.translate(actorPosition);
modelMatrix.rotate(actorRotation);
modelMatrix.scale(actorScale);
actor.applyModelMatrix(modelMatrix);
}
public boolean handleEvent(Event event){
boolean propagate = true;
if(event instanceof DragEvent){
if(onDragStart != null && ((DragEvent)event).getType() == DragEventType.START){
if(!onDragStart.execute((DragEvent)event)){
propagate = false;
}
}
if(onDrag != null && ((DragEvent)event).getType() == DragEventType.DRAG){
if(!onDrag.execute((DragEvent)event)){
propagate = false;
}
}
if(onDragRelease != null && ((DragEvent)event).getType() == DragEventType.RELEASE){
if(!onDragRelease.execute((DragEvent)event)){
propagate = false;
}
}
}
return propagate;
}
@Override
public void setOnDragStart(DragEventCallback callback) {
onDragStart = callback;
}
@Override
public void setOnDrag(DragEventCallback callback) {
onDrag = callback;
}
@Override
public void setOnDragRelease(DragEventCallback callback) {
onDragRelease = callback;
}
}