Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reintroduce BeforeBake* and AfterBake* model modifiers #4320

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,38 @@ interface Context {

/**
* Event access to monitor unbaked model loads and replace the loaded model.
*
* <p>Replacements done by listeners of this callback <b>do</b> affect child models (that is, models whose
* parent hierarchy contains the replaced model), unlike {@link #modifyModelBeforeBake}.
*/
Event<ModelModifier.OnLoad> modifyModelOnLoad();

/**
* Event access to replace the unbaked model used for baking without replacing the cached model.
*
* <p>Replacements done by listeners of this callback <b>do not</b> affect child models (that is, models whose
* parent hierarchy contains the replaced model), unlike {@link #modifyModelOnLoad}.
*/
Event<ModelModifier.BeforeBake> modifyModelBeforeBake();

/**
* Event access to replace the baked model.
*/
Event<ModelModifier.AfterBake> modifyModelAfterBake();

/**
* Event access to monitor unbaked block model loads and replace the loaded model.
*/
Event<ModelModifier.OnLoadBlock> modifyBlockModelOnLoad();

/**
* Event access to replace the unbaked block model used for baking.
*/
Event<ModelModifier.BeforeBakeBlock> modifyBlockModelBeforeBake();

/**
* Event access to replace the baked block model.
*/
Event<ModelModifier.AfterBakeBlock> modifyBlockModelAfterBake();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@
import org.jetbrains.annotations.Nullable;

import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.Baker;
import net.minecraft.client.render.model.GroupableModel;
import net.minecraft.client.render.model.ModelBakeSettings;
import net.minecraft.client.render.model.ResolvableModel;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.util.ModelIdentifier;
Expand All @@ -44,7 +47,7 @@
* and separate phases are provided for mods that wrap their own models and mods that need to wrap models of other mods
* or wrap models arbitrarily.
*
* <p>These callbacks are invoked for <b>every single model that is loaded</b>, so implementations should be
* <p>These callbacks are invoked for <b>every single model that is loaded or baked</b>, so implementations should be
* as efficient as possible.
*/
public final class ModelModifier {
Expand Down Expand Up @@ -75,7 +78,11 @@ public interface OnLoad {
* <p>If the given model is {@code null}, its corresponding identifier was requested during
* {@linkplain ResolvableModel#resolve resolution} but the model was not loaded normally; i.e. through a JSON
* file, possibly because that file did not exist. If a non-{@code null} model is returned in this case,
* resolution will continue without warnings or errors.
* resolution will continue without warnings or errors. This callback can return a {@code null} model, which
* has the same meaning as described earlier, so it is unlikely that an implementor should need to return
* {@code null} unless directly returning the given model.
*
* <p>For further information, see the docs of {@link ModelLoadingPlugin.Context#modifyModelOnLoad()}.
*
* @param model the current unbaked model instance
* @param context context with additional information about the model/loader
Expand All @@ -97,6 +104,86 @@ interface Context {
}
}

@FunctionalInterface
public interface BeforeBake {
/**
* This handler is invoked to allow modification of the unbaked model instance right before it is baked.
*
* <p>For further information, see the docs of {@link ModelLoadingPlugin.Context#modifyModelBeforeBake()}.
*
* @param model the current unbaked model instance
* @param context context with additional information about the model/loader
* @return the model that should be used in this scenario. If no changes are needed, just return {@code model} as-is.
* @see ModelLoadingPlugin.Context#modifyModelBeforeBake
*/
UnbakedModel modifyModelBeforeBake(UnbakedModel model, Context context);

/**
* The context for a before bake model modification event.
*/
@ApiStatus.NonExtendable
interface Context {
/**
* The identifier of the model being baked.
*/
Identifier id();

/**
* The settings this model is being baked with.
*/
ModelBakeSettings settings();

/**
* The baker being used to bake this model. It can be used to {@linkplain Baker#bake bake models} and
* {@linkplain Baker#getSpriteGetter get sprites}. Note that baking a model which was not previously
* {@linkplain ResolvableModel.Resolver#resolve resolved} will log a warning and return the missing model.
*/
Baker baker();
}
}

@FunctionalInterface
public interface AfterBake {
/**
* This handler is invoked to allow modification of the baked model instance right after it is baked and before
* it is cached.
*
* @param model the current baked model instance
* @param context context with additional information about the model/loader
* @return the model that should be used in this scenario. If no changes are needed, just return {@code model} as-is.
* @see ModelLoadingPlugin.Context#modifyModelAfterBake
*/
BakedModel modifyModelAfterBake(BakedModel model, Context context);

/**
* The context for an after bake model modification event.
*/
@ApiStatus.NonExtendable
interface Context {
/**
* The identifier of the model being baked.
*/
Identifier id();

/**
* The unbaked model that is being baked.
*/
UnbakedModel sourceModel();

/**
* The settings this model is being baked with.
*/
ModelBakeSettings settings();

/**
* The baker being used to bake this model. It can be used to {@linkplain Baker#bake bake models} and
* {@linkplain Baker#getSpriteGetter get sprites}. Note that baking a model which was not previously
* {@linkplain ResolvableModel.Resolver#resolve resolved} will log a warning and return the missing model.
*/
Baker baker();
}
}

@FunctionalInterface
public interface OnLoadBlock {
/**
Expand Down Expand Up @@ -126,5 +213,72 @@ interface Context {
}
}

@FunctionalInterface
public interface BeforeBakeBlock {
/**
* This handler is invoked to allow modification of the unbaked block model instance right before it is baked.
*
* @param model the current unbaked model instance
* @param context context with additional information about the model/loader
* @return the model that should be used in this scenario. If no changes are needed, just return {@code model} as-is.
* @see ModelLoadingPlugin.Context#modifyBlockModelBeforeBake
*/
GroupableModel modifyModelBeforeBake(GroupableModel model, Context context);

/**
* The context for a before bake block model modification event.
*/
@ApiStatus.NonExtendable
interface Context {
/**
* The identifier of the model being baked.
*/
ModelIdentifier id();

/**
* The baker being used to bake this model. It can be used to {@linkplain Baker#bake bake models} and
* {@linkplain Baker#getSpriteGetter get sprites}. Note that baking a model which was not previously
* {@linkplain ResolvableModel.Resolver#resolve resolved} will log a warning and return the missing model.
*/
Baker baker();
}
}

@FunctionalInterface
public interface AfterBakeBlock {
/**
* This handler is invoked to allow modification of the baked block model instance right after it is baked.
*
* @param model the current baked model instance
* @param context context with additional information about the model/loader
* @return the model that should be used in this scenario. If no changes are needed, just return {@code model} as-is.
* @see ModelLoadingPlugin.Context#modifyBlockModelAfterBake
*/
BakedModel modifyModelAfterBake(BakedModel model, Context context);

/**
* The context for an after bake block model modification event.
*/
@ApiStatus.NonExtendable
interface Context {
/**
* The identifier of the model being baked.
*/
ModelIdentifier id();

/**
* The unbaked model that is being baked.
*/
GroupableModel sourceModel();

/**
* The baker being used to bake this model. It can be used to {@linkplain Baker#bake bake models} and
* {@linkplain Baker#getSpriteGetter get sprites}. Note that baking a model which was not previously
* {@linkplain ResolvableModel.Resolver#resolve resolved} will log a warning and return the missing model.
*/
Baker baker();
}
}

private ModelModifier() { }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.fabric.impl.client.model.loading;

import org.jetbrains.annotations.Nullable;

public interface ModelBakerHooks {
@Nullable
ModelLoadingEventDispatcher fabric_getDispatcher();
}
Loading