Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesTKhan committed Jun 28, 2023
2 parents 73f415e + 0e176dc commit b293dec
Show file tree
Hide file tree
Showing 6 changed files with 534 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import com.badlogic.gdx.Gdx
import com.badlogic.gdx.files.FileHandle
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.PixmapIO
import com.badlogic.gdx.graphics.g3d.Model
import com.badlogic.gdx.utils.Array
import com.badlogic.gdx.utils.ObjectSet
import com.kotcrab.vis.ui.util.dialog.Dialogs
Expand Down Expand Up @@ -49,6 +50,7 @@ import com.mbrlabs.mundus.editor.events.LogEvent
import com.mbrlabs.mundus.editor.events.LogType
import com.mbrlabs.mundus.editor.ui.UI
import com.mbrlabs.mundus.editor.utils.Log
import net.mgsx.gltf.exporters.GLTFExporter
import org.apache.commons.io.FileUtils
import org.apache.commons.io.FilenameUtils
import java.io.BufferedOutputStream
Expand Down Expand Up @@ -272,6 +274,36 @@ class EditorAssetManager(assetsRoot: FileHandle) : AssetManager(assetsRoot) {
return asset
}

/**
* Creates a new model asset. This variant of the method
* is used when the model does not have a file, e.g.
* a model that was generated by code (planes, cubes, etc)..
* It uses GLTF exporter to create a new gltf model file.
*
* @param fileName name of the model file
* @param model the loaded model
*/
@Throws(IOException::class, AssetAlreadyExistsException::class)
fun createModelAsset(fileName: String, model: Model): ModelAsset {
val modelFilename = fileName
val metaFilename = modelFilename + ".meta"

// create meta file
val metaPath = FilenameUtils.concat(rootFolder.path(), metaFilename)
val meta = createNewMetaFile(FileHandle(metaPath), AssetType.MODEL)

val assetFile = FileHandle(FilenameUtils.concat(rootFolder.path(), modelFilename))
val exporter = GLTFExporter()
exporter.export(model, assetFile)

// load & return asset
val asset = ModelAsset(meta, assetFile)
asset.load()

addAsset(asset)
return asset
}

/**
* Creates a new terrainAsset asset.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ class ModelImporter(private val registry: Registry) : SettingsChangedEvent.Setti
* required for resolving image/texture files.
*/
fun populateMaterialAsset(
importedModel: FileHandleWithDependencies,
importedModel: FileHandleWithDependencies?,
assetManager: EditorAssetManager,
materialToUse: Material,
materialAssetToPopulate: MaterialAsset,
Expand Down Expand Up @@ -126,7 +126,7 @@ class ModelImporter(private val registry: Registry) : SettingsChangedEvent.Setti
// Texture Attributes
if (materialToUse.has(PBRTextureAttribute.BaseColorTexture)) {
materialAssetToPopulate.diffuseTexture = getTextureAssetForMaterial(
importedModel,
importedModel!!,
assetManager,
materialToUse.id,
PBRTextureAttribute.BaseColorTexture)
Expand All @@ -135,7 +135,7 @@ class ModelImporter(private val registry: Registry) : SettingsChangedEvent.Setti

if (materialToUse.has(PBRTextureAttribute.NormalTexture)) {
materialAssetToPopulate.normalMap = getTextureAssetForMaterial(
importedModel,
importedModel!!,
assetManager,
materialToUse.id,
PBRTextureAttribute.NormalTexture
Expand All @@ -145,7 +145,7 @@ class ModelImporter(private val registry: Registry) : SettingsChangedEvent.Setti

if (materialToUse.has(PBRTextureAttribute.EmissiveTexture)) {
materialAssetToPopulate.emissiveTexture = getTextureAssetForMaterial(
importedModel,
importedModel!!,
assetManager,
materialToUse.id,
PBRTextureAttribute.EmissiveTexture
Expand All @@ -155,7 +155,7 @@ class ModelImporter(private val registry: Registry) : SettingsChangedEvent.Setti

if (materialToUse.has(PBRTextureAttribute.MetallicRoughnessTexture)) {
materialAssetToPopulate.metallicRoughnessTexture = getTextureAssetForMaterial(
importedModel,
importedModel!!,
assetManager,
materialToUse.id,
PBRTextureAttribute.MetallicRoughnessTexture
Expand All @@ -165,7 +165,7 @@ class ModelImporter(private val registry: Registry) : SettingsChangedEvent.Setti

if (materialToUse.has(PBRTextureAttribute.OcclusionTexture)) {
materialAssetToPopulate.occlusionTexture = getTextureAssetForMaterial(
importedModel,
importedModel!!,
assetManager,
materialToUse.id,
PBRTextureAttribute.OcclusionTexture
Expand Down
106 changes: 76 additions & 30 deletions editor/src/main/com/mbrlabs/mundus/editor/events/EventBus.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,70 +16,116 @@

package com.mbrlabs.mundus.editor.events;

import com.mbrlabs.mundus.editor.utils.ReflectionUtils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.mbrlabs.mundus.editor.utils.ReflectionUtils;
import java.util.Map;

/**
* Simple Event bus via reflection.
*
* <p>
* Subscribers need to provide a public method, annotated with @Subscribe and 1
* parameter as event type.
*
* <p>
* Inspired by the Otto Event Bus for Android.
*
* @author Marcus Brummer
* @version 12-12-2015
*/
// TODO improve/test performance might not be that great
public class EventBus {

private class EventBusExcetion extends RuntimeException {
private EventBusExcetion(String s) {
private static class EventBusException extends RuntimeException {
private EventBusException(String s) {
super(s);
}
}

private List<Object> subscribers;
/**
* Tracks the subscriber methods for each event type.
*/
private static class SubscriberMethod {
final Object instance;
final Method method;

SubscriberMethod(Object instance, Method method) {
this.instance = instance;
this.method = method;
}
}

// Maps the event class to subscriber methods, cached for performance
private final Map<Class<?>, List<SubscriberMethod>> subscribersMap;

public EventBus() {
subscribers = new LinkedList<>();
subscribersMap = new HashMap<>();
}

/**
* Registers all subscriber methods of the given object.
* For performance reasons we cache the subscriber methods for each event on register.
*
* @param subscriber the object with subscriber methods
*/
public void register(Object subscriber) {
subscribers.add(subscriber);
// Loop over each method in the subscriber
for (Method method : subscriber.getClass().getDeclaredMethods()) {
if (!isSubscriber(method)) continue;

if (method.getParameterTypes().length != 1) {
throw new EventBusException("Size of parameter list of method " + method.getName() + " in "
+ subscriber.getClass().getName() + " must be 1");
}

Class<?> eventType = method.getParameterTypes()[0];

// Get the list of subscribers for this event
List<SubscriberMethod> subscribers = subscribersMap.computeIfAbsent(eventType, k -> new ArrayList<>());
subscribers.add(new SubscriberMethod(subscriber, method));
}
}

/**
* Unregisters all subscriber methods of the given object.
* @param subscriber
*/
public void unregister(Object subscriber) {
subscribers.remove(subscriber);
// Iterate over each event type in the map, remove if matched
for (List<SubscriberMethod> methods : subscribersMap.values()) {
methods.removeIf(subscriberMethod -> subscriberMethod.instance.equals(subscriber));
}
}

/**
* Posts an event to all subscribers of this event type.
* @param event the event to post
*/
public void post(Object event) {
try {
final Class eventType = event.getClass();
for (Object subscriber : subscribers.toArray()) {
for (Method method : subscriber.getClass().getDeclaredMethods()) {
if (isSubscriber(method)) {
if (method.getParameterTypes().length != 1) {
throw new EventBusExcetion("Size of parameter list of method " + method.getName() + " in "
+ subscriber.getClass().getName() + " must be 1");
}

if (method.getParameterTypes()[0].equals(eventType)) {
// System.out.println(subscriber.getClass().getName());
method.invoke(subscriber, eventType.cast(event));
}
}
}
// Get the list of subscribers for this event
List<SubscriberMethod> subscribers = subscribersMap.get(event.getClass());

if (subscribers == null) return;

// Call each subscriber method
for (SubscriberMethod subscriberMethod : subscribers) {
try {
subscriberMethod.method.invoke(subscriberMethod.instance, event);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}

/**
* Checks if the given method is a subscriber.
* Slow with reflection, but we only check it on register.
*
* @param method the method to check
* @return true if the method is a subscriber
*/
private boolean isSubscriber(Method method) {
// check if @Subscribe is directly used in class
boolean isSub = ReflectionUtils.hasMethodAnnotation(method, Subscribe.class);
Expand Down
Loading

0 comments on commit b293dec

Please sign in to comment.