diff --git a/package.json b/package.json index 323bd300..67744e52 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "title": "Animated Java", "icon": "icon.svg", "description": "Effortlessly craft complex animations for Minecraft: Java Edition", - "version": "1.8.0-beta.4", + "version": "1.8.0-beta.5", "min_blockbench_version": "4.12.0", "max_blockbench_version": "4.12.6", "variant": "desktop", diff --git a/src/formats/blueprint/index.ts b/src/formats/blueprint/index.ts index 336a5b81..435c3e1b 100644 --- a/src/formats/blueprint/index.ts +++ b/src/formats/blueprint/index.ts @@ -146,6 +146,20 @@ export interface IBlueprintFormatJSON { collections?: ICollectionJSON[] } +export function fixCubeRotation(cube: Cube) { + const maxRotation = Math.max(...cube.rotation) + const minRotation = Math.min(...cube.rotation) + if (maxRotation <= 45 && minRotation >= -45) return + // Use the rotation with the largest absolute value + const rotation = Math.abs(maxRotation) >= Math.abs(minRotation) ? maxRotation : minRotation + const axis = cube.rotation.indexOf(rotation) + + const previousSelected = Project!.selected_elements + Project!.selected_elements = [cube] + rotateOnAxis(() => rotation, axis, true) + Project!.selected_elements = previousSelected +} + //region > Convert export function convertToBlueprint() { // Convert the current project to a Blueprint @@ -156,13 +170,19 @@ export function convertToBlueprint() { group.createUniqueName(Group.all.filter(g => g !== group)) group.sanitizeName() } + for (const animation of Blockbench.Animation.all) { animation.createUniqueName(Blockbench.Animation.all.filter(a => a !== animation)) animation.name = sanitizeStorageKey(animation.name) } + for (const cube of Cube.all) { cube.setUVMode(false) + + fixCubeRotation(cube) } + + Canvas.updateAll() } export function getDefaultProjectSettings() { @@ -278,6 +298,13 @@ export const BLUEPRINT_FORMAT = registerModelFormat( component: ProjectTitleSvelte, props: { pluginMode: project.pluginMode }, }) + + for (const cube of Cube.all) { + cube.setUVMode(false) + fixCubeRotation(cube) + } + + Canvas.updateAll() }) }, @@ -353,14 +380,8 @@ export function projectTargetVersionIsAtLeast(version: string): boolean { return !compareVersions(version, Project!.animated_java.target_minecraft_version) } -export function shouldEnableRotationLock(): boolean { - if (!activeProjectIsBlueprintFormat()) return false - - if (projectTargetVersionIsAtLeast('1.21.6')) { - return false - } - - return !( +export function hasNonElementSelection(): boolean { + return ( !!Group.first_selected || !!AnimatedJava.TextDisplay.selected.length || !!AnimatedJava.VanillaItemDisplay.selected.length || @@ -376,20 +397,20 @@ export function shouldEnableRotationLock(): boolean { ) } -export function updateRotationLock() { - if (!activeProjectIsBlueprintFormat()) return - const format = BLUEPRINT_FORMAT.get()! - // If any of these node types are selected, we disable rotation lock. - format.rotation_limit = shouldEnableRotationLock() - format.rotation_snap = format.rotation_limit -} - -export function disableRotationLock() { +export function updateRotationConstraints() { if (!activeProjectIsBlueprintFormat()) return const format = BLUEPRINT_FORMAT.get()! + if (!format) { + console.error('Animated Java Blueprint format is not registered!') + return + } - format.rotation_limit = false - format.rotation_snap = false + // Rotation is always limited when selecting an element + format.rotation_limit = !hasNonElementSelection() + if (!projectTargetVersionIsAtLeast('1.21.6') /* < 1.21.6 */) { + // But only snaps to 22.5 degree increments on versions before 1.21.6 + format.rotation_snap = format.rotation_limit + } } EVENTS.SELECT_PROJECT.subscribe(project => { @@ -402,13 +423,12 @@ EVENTS.UNSELECT_PROJECT.subscribe(project => { EVENTS.UNSELECT_AJ_PROJECT.publish(project) } }) -EVENTS.UPDATE_SELECTION.subscribe(updateRotationLock) +EVENTS.UPDATE_SELECTION.subscribe(updateRotationConstraints) EVENTS.SELECT_AJ_PROJECT.subscribe(() => { requestAnimationFrame(() => { - updateRotationLock() + updateRotationConstraints() }) }) EVENTS.UNSELECT_AJ_PROJECT.subscribe(project => { if (project.visualBoundingBox) scene.remove(project.visualBoundingBox) - disableRotationLock() }) diff --git a/src/interface/dialog/blueprintSettings.ts b/src/interface/dialog/blueprintSettings.ts index ef826329..a13e107d 100644 --- a/src/interface/dialog/blueprintSettings.ts +++ b/src/interface/dialog/blueprintSettings.ts @@ -3,7 +3,7 @@ import { updateAllCubeOutlines } from 'src/mods/cube' import { SUPPORTED_MINECRAFT_VERSIONS } from 'src/systems/global' import BlueprintSettingsDialogSvelteComponent from '../../components/blueprintSettingsDialog.svelte' import { PACKAGE } from '../../constants' -import { updateRotationLock } from '../../formats/blueprint' +import { updateRotationConstraints } from '../../formats/blueprint' import { defaultValues, type ExportMode } from '../../formats/blueprint/settings' import { sanitizeStorageKey } from '../../util/minecraftUtil' import { Valuable } from '../../util/stores' @@ -134,7 +134,7 @@ export function openBlueprintSettingsDialog() { preventKeybinds: true, onConfirm() { setSettings(settings) - updateRotationLock() + updateRotationConstraints() updateAllCubeOutlines() Canvas.updateAll() }, diff --git a/src/mods/eventHooks.ts b/src/mods/eventHooks.ts index 6f8a66e5..fd29c0f5 100644 --- a/src/mods/eventHooks.ts +++ b/src/mods/eventHooks.ts @@ -46,3 +46,16 @@ registerPropertyOverrideMod({ } }, }) + +registerPropertyOverrideMod({ + id: `animated-java:event-hook/pre-select-project-event`, + object: ModelProject.prototype, + key: 'select', + + get: original => { + return function (this: ModelProject) { + EVENTS.PRE_SELECT_PROJECT.publish(this) + return original.call(this) + } + }, +}) diff --git a/src/mods/modelFormatSelectMod.ts b/src/mods/modelFormatSelectMod.ts deleted file mode 100644 index 0c27dd33..00000000 --- a/src/mods/modelFormatSelectMod.ts +++ /dev/null @@ -1,21 +0,0 @@ -import EVENTS from '../util/events' -import { registerMod } from '../util/moddingTools' - -registerMod({ - id: `animated-java:model-format-pre-select-project-event`, - - apply: () => { - const original = ModelProject.prototype.select - - ModelProject.prototype.select = function (this: ModelProject) { - EVENTS.PRE_SELECT_PROJECT.publish(this) - return original.call(this) - } - - return { original } - }, - - revert: ({ original }) => { - ModelProject.prototype.select = original - }, -}) diff --git a/src/pluginPackage/changelog.json b/src/pluginPackage/changelog.json index b17c1583..97ba3027 100644 --- a/src/pluginPackage/changelog.json +++ b/src/pluginPackage/changelog.json @@ -404,5 +404,21 @@ ] } ] + }, + "1.8.0-beta.5": { + "title": "v1.8.0-beta.5", + "author": "Titus Evans (SnaveSutit)", + "date": "2025-10-19", + "categories": [ + { + "title": "Fixes", + "list": [ + "Fixed cube rotations in 1.21.6+ allowing rotation values outside the -45..45 degree range", + "Fixed rotation limits not being enforced when converting to a Blueprint.", + "Fixed rotation limit not being enforced when rotating cubes.", + "Fixed export crash due to invalid tag reference." + ] + } + ] } } diff --git a/src/systems/datapackCompiler/1.20.4/global.mcb b/src/systems/datapackCompiler/1.20.4/global.mcb index 0c224060..3196d732 100644 --- a/src/systems/datapackCompiler/1.20.4/global.mcb +++ b/src/systems/datapackCompiler/1.20.4/global.mcb @@ -117,9 +117,6 @@ dir global { # Removes locators and cameras owned by the rig, even if they're not included in the currently loaded export. function outdated_rig { - # Assert that the function is being executed as a root entity. - debug assert executed_as_root_entity <%TAGS.GLOBAL_ROOT()%> - execute on passengers if entity @s[tag=<%TAGS.GLOBAL_DATA()%>] run block as_data { data remove storage <%temp_storage%> args data remove storage <%temp_storage%> uuids diff --git a/src/systems/datapackCompiler/1.20.4/global.mcbt b/src/systems/datapackCompiler/1.20.4/global.mcbt index 5b9239b5..c6b8bc0b 100644 --- a/src/systems/datapackCompiler/1.20.4/global.mcbt +++ b/src/systems/datapackCompiler/1.20.4/global.mcbt @@ -1,8 +1,8 @@ template debug { - with assert:literal executed_as_root_entity:literal root_tag:literal { + with assert:literal executed_as_root_entity:literal root_tag:js { IF (debug_mode) { execute unless entity @s[type=minecraft:item_display,tag=<%root_tag%>] run return run \ - tellraw @a <%TELLRAW.FUNCTION_NOT_EXECUTED_AS_ROOT_ERROR(context.functions.at(-1))%> + tellraw @a <%TELLRAW.FUNCTION_NOT_EXECUTED_AS_ROOT_ERROR(context.functions.at(-1), root_tag)%> } } } \ No newline at end of file diff --git a/src/systems/datapackCompiler/1.21.2/global.mcb b/src/systems/datapackCompiler/1.21.2/global.mcb index 446f2532..31f53747 100644 --- a/src/systems/datapackCompiler/1.21.2/global.mcb +++ b/src/systems/datapackCompiler/1.21.2/global.mcb @@ -117,9 +117,6 @@ dir global { # Removes locators and cameras owned by the rig, even if they're not included in the currently loaded export. function outdated_rig { - # Assert that the function is being executed as a root entity. - debug assert executed_as_root_entity <%TAGS.GLOBAL_ROOT()%> - execute on passengers if entity @s[tag=<%TAGS.GLOBAL_DATA()%>] run block as_data { data remove storage <%temp_storage%> args data remove storage <%temp_storage%> uuids diff --git a/src/systems/datapackCompiler/1.21.5/global.mcb b/src/systems/datapackCompiler/1.21.5/global.mcb index 94c49749..b50f7b78 100644 --- a/src/systems/datapackCompiler/1.21.5/global.mcb +++ b/src/systems/datapackCompiler/1.21.5/global.mcb @@ -117,9 +117,6 @@ dir global { # Removes locators and cameras owned by the rig, even if they're not included in the currently loaded export. function outdated_rig { - # Assert that the function is being executed as a root entity. - debug assert executed_as_root_entity <%TAGS.GLOBAL_ROOT()%> - execute on passengers if entity @s[tag=<%TAGS.GLOBAL_DATA()%>] run block as_data { data remove storage <%temp_storage%> args data remove storage <%temp_storage%> uuids diff --git a/src/systems/datapackCompiler/tellraw.ts b/src/systems/datapackCompiler/tellraw.ts index db6cc520..be84b04f 100644 --- a/src/systems/datapackCompiler/tellraw.ts +++ b/src/systems/datapackCompiler/tellraw.ts @@ -2,7 +2,6 @@ import { toSmallCaps } from 'src/util/minecraftUtil' import { type IRenderedAnimation } from '../animationRenderer' import { JsonText, TextElement } from '../jsonText' import { type IRenderedVariant } from '../rigRenderer' -import { TAGS } from './tags' const TELLRAW_PREFIX = () => new JsonText([ @@ -120,12 +119,10 @@ namespace TELLRAW { .toString() .replaceAll('\\n', '\\\\n') - export const FUNCTION_NOT_EXECUTED_AS_ROOT_ERROR = (functionPath: string) => { + export const FUNCTION_NOT_EXECUTED_AS_ROOT_ERROR = (functionPath: string, tag: string) => { const hoverText = new JsonText([{ text: functionPath, color: 'yellow' }, '']).flatten() - const exampleCommand = `/execute as @e[tag=${TAGS.PROJECT_ROOT( - Project!.animated_java.export_namespace - )}] run function ${functionPath}` + const exampleCommand = `/execute as @e[tag=${tag}] run function ${functionPath}` return TELLRAW_ERROR('Function Not Executed as Root Entity', [ !compareVersions('1.21.5', Project!.animated_java.target_minecraft_version) diff --git a/src/systems/util.ts b/src/systems/util.ts index d48006b1..f11f25c0 100644 --- a/src/systems/util.ts +++ b/src/systems/util.ts @@ -102,7 +102,11 @@ export function isCubeValid(cube: Cube): '1.21.6+' | 'valid' | 'invalid' { totalRotation === cube.rotation[1] || totalRotation === cube.rotation[2] - if (isSingleAxisRotation && projectTargetVersionIsAtLeast('1.21.6')) return '1.21.6+' + if (isSingleAxisRotation && projectTargetVersionIsAtLeast('1.21.6')) { + // Rotation values still need to be within -45 and 45 degrees + if (totalRotation <= 45 && totalRotation >= -45) return '1.21.6+' + else return 'invalid' + } const isRotationInAllowedSteps = totalRotation === -45 || diff --git a/test-packs/latest/blueprints/armor_stand_latest.ajblueprint b/test-packs/latest/blueprints/armor_stand_latest.ajblueprint index 73277744..f908069b 100644 --- a/test-packs/latest/blueprints/armor_stand_latest.ajblueprint +++ b/test-packs/latest/blueprints/armor_stand_latest.ajblueprint @@ -1,7 +1,7 @@ { "meta": { "format": "animated-java:format/blueprint", - "format_version": "1.8.0-beta.3", + "format_version": "1.8.0-beta.4", "uuid": "167b27cd-b559-3f13-a97c-0841fe21f1d1", "save_location": "D:\\github-repos\\animated-java\\old-animated-java\\test-packs\\latest\\blueprints\\armor_stand_latest.ajblueprint", "last_used_export_namespace": "armor_stand"