block requirements
This commit is contained in:
+10
-5
@@ -785,10 +785,13 @@
|
||||
function refreshBlockGuideFaces() {
|
||||
const roots = Group.all.filter((group) => group.name.startsWith(BLOCK_GUIDE_PREFIX)
|
||||
&& !isBlockRequirementGuide(group.parent));
|
||||
const elements = [];
|
||||
for (const root of roots) {
|
||||
hideInternalBlockGuideFaces(Cube.all.filter((cube) => cube.getAllAncestors().includes(root)));
|
||||
const cubes = Cube.all.filter((cube) => cube.getAllAncestors().includes(root));
|
||||
hideInternalBlockGuideFaces(cubes);
|
||||
elements.push(...cubes);
|
||||
}
|
||||
if (roots.length) Canvas.updateAllFaces();
|
||||
if (elements.length) Canvas.updateView({ elements, element_aspects: { faces: true, uv: true } });
|
||||
}
|
||||
|
||||
function rebuildBlockRequirementGuides(animationId, entry) {
|
||||
@@ -826,7 +829,9 @@
|
||||
}
|
||||
Project[BLOCK_REQUIREMENTS_PROPERTY] = JSON.stringify(updated);
|
||||
hideInternalBlockGuideFaces(createdElements);
|
||||
Canvas.updateAll();
|
||||
// Rebuilding every cube would reset forced actor materials in single-texture formats.
|
||||
Canvas.updateView({ elements: createdElements, groups: createdGroups,
|
||||
element_aspects: { transform: true, geometry: true, faces: true, uv: true, visibility: true } });
|
||||
for (const cube of createdElements) applyBlockRequirementGuideMaterial(cube);
|
||||
Undo.finishEdit(entry ? 'Set block requirement' : 'Remove block requirement',
|
||||
{ outliner: true, elements: createdElements, groups: createdGroups, block_requirement_edit: true });
|
||||
@@ -914,7 +919,7 @@
|
||||
blockRequirementPanel = new Panel('animationdirector_block_requirements', {
|
||||
name: 'Block Requirements', icon: 'view_in_ar', condition: () => !!Project,
|
||||
growable: true, resizable: true, min_height: 240, expand_button: true,
|
||||
default_position: { slot: 'right_bar', height: 520, float_size: [360, 620] },
|
||||
default_position: { slot: 'left_bar', height: 520, float_size: [360, 620] },
|
||||
component: {
|
||||
data() { return { projectId: null, animationId: '', draftId: '', ids: [], form: {}, values: {}, error: '', status: '', dirty: false }; },
|
||||
computed: {
|
||||
@@ -1020,7 +1025,7 @@
|
||||
const selected = parseAfwStageAnimationName(getSelectedAnimation());
|
||||
const ids = blockRequirementAnimationIds();
|
||||
view.load(selected?.id || (view.projectId === Project.uuid && view.animationId) || ids[0] || '');
|
||||
if (blockRequirementPanel.slot === 'hidden') blockRequirementPanel.moveTo('right_bar');
|
||||
if (blockRequirementPanel.slot === 'hidden') blockRequirementPanel.moveTo('left_bar');
|
||||
blockRequirementPanel.folded = false;
|
||||
blockRequirementPanel.getContainerPanel().selectTab(blockRequirementPanel);
|
||||
blockRequirementPanel.update();
|
||||
|
||||
@@ -17,6 +17,7 @@ function harness() {
|
||||
const events = new Map();
|
||||
const previewEvents = new Map();
|
||||
const timers = new Map();
|
||||
const previewUpdates = [];
|
||||
let sequence = 0;
|
||||
class Group {
|
||||
static all = [];
|
||||
@@ -57,8 +58,20 @@ function harness() {
|
||||
MenuBar: { menus: { tools: { addAction() {} } }, update() {} },
|
||||
THREE: { MeshBasicMaterial: class { constructor(options) { Object.assign(this, options); } }, DoubleSide: 2 },
|
||||
Canvas: {
|
||||
updateAll() { for (const cube of Cube.all) previewEvents.get('update_faces')?.({ element: cube }); },
|
||||
updateAll() {
|
||||
for (const cube of Cube.all) {
|
||||
cube.mesh.material = 'selected-shared-texture';
|
||||
previewEvents.get('update_faces')?.({ element: cube });
|
||||
}
|
||||
},
|
||||
updateAllFaces() { this.updateAll(); },
|
||||
updateView(options) {
|
||||
previewUpdates.push(options);
|
||||
for (const cube of options.elements || []) {
|
||||
cube.mesh.material = 'selected-shared-texture';
|
||||
if (options.element_aspects?.faces) previewEvents.get('update_faces')?.({ element: cube });
|
||||
}
|
||||
},
|
||||
},
|
||||
Undo: {
|
||||
initEdit(aspects) { edits.push({ before: project.animationdirector_block_requirements, aspects }); },
|
||||
@@ -72,7 +85,7 @@ function harness() {
|
||||
console,
|
||||
};
|
||||
vm.runInNewContext(source, context);
|
||||
return { ...context.blockTest, context, project, dialogs, exports, errors, edits, events, previewEvents, timers, Group, Cube };
|
||||
return { ...context.blockTest, context, project, dialogs, exports, errors, edits, events, previewEvents, timers, previewUpdates, Group, Cube };
|
||||
}
|
||||
|
||||
function wallForm(overrides = {}) {
|
||||
@@ -80,6 +93,31 @@ function wallForm(overrides = {}) {
|
||||
facing: '', clearance_width: 1, clearance_height: 2, clearance_depth: 1, wall_thickness: 1, ...overrides };
|
||||
}
|
||||
|
||||
test('building, editing, refreshing and removing guides never resets actor or folder texture overrides', () => {
|
||||
const h = harness();
|
||||
const actor = new h.Group({ name: 'actor1_body' });
|
||||
actor.init(); actor.addTo('root');
|
||||
const cubes = ['actor-texture', 'folder-override-texture'].map((material, index) => {
|
||||
const cube = new h.Cube({ name: `actor1_cube${index}`, from: [0, 0, 0], to: [16, 16, 16] });
|
||||
cube.init(); cube.addTo(actor);
|
||||
cube.mesh.material = material;
|
||||
for (const face of Object.values(cube.faces)) face.texture = material;
|
||||
return cube;
|
||||
});
|
||||
const before = cubes.map((cube) => ({ material: cube.mesh.material, faces: JSON.stringify(cube.faces) }));
|
||||
h.context.registration.onload();
|
||||
h.rebuildBlockRequirementGuides('test', h.readBlockRequirementForm(wallForm()));
|
||||
h.rebuildBlockRequirementGuides('test', h.readBlockRequirementForm(wallForm({ width_min: 3, clearance_depth: 2 })));
|
||||
h.refreshBlockGuideFaces();
|
||||
h.rebuildBlockRequirementGuides('test', null);
|
||||
assert.deepEqual(cubes.map((cube) => ({ material: cube.mesh.material, faces: JSON.stringify(cube.faces) })), before);
|
||||
for (const update of h.previewUpdates) {
|
||||
assert.ok(update.elements.every((cube) => !cubes.includes(cube)));
|
||||
assert.ok((update.groups || []).every((group) => group !== actor));
|
||||
}
|
||||
assert.equal(h.previewUpdates.length, 4);
|
||||
});
|
||||
|
||||
test('guide cubes omit internal faces, preserve colored boundaries and restore newly exposed faces', () => {
|
||||
const h = harness();
|
||||
const make = (kind, from, to) => new h.Cube({ name: `__ad_block_requirement_${kind}_test`, from, to });
|
||||
|
||||
Reference in New Issue
Block a user