Editor offset, global On click, Coin container in the jump-and-run seed
- SceneObject.editorOffset (x/y): shifts only where an object is drawn in the Scene tab, cascades to children, undo-able with a reset action. Never written into container templates. - On click without an owner now fires for any click inside the camera frame instead of hit-testing the (editor-only) behavior symbol. - seed-jumprun: coins are a "Coin" container (sprite + trigger), nested containers are expanded recursively, Destroy targets the coin's parent, and the clock uses a Ceil node instead of ToText. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2511483a67
commit
3234eb480f
14 files changed
+229
-53
No files matched your search
@@ -13,6 +13,7 @@ import {
|
||||
ClearOverrideCommand,
|
||||
MoveSceneObjectCommand,
|
||||
RenameSceneObjectCommand,
|
||||
SetEditorOffsetCommand,
|
||||
SetOverrideCommand,
|
||||
SetParentCommand,
|
||||
} from '../../core/commands/sceneObjectCommands';
|
||||
@@ -22,7 +23,7 @@ import type { Asset, BehaviorAsset, SceneAsset } from '../../core/model/Asset';
|
||||
import { isPlaceableType } from '../../core/model/AssetTypes';
|
||||
import { type TemplateLink, templateLinkOf } from '../../core/model/container';
|
||||
import { isSelfOrAncestor, treeOrder } from '../../core/model/hierarchy';
|
||||
import type { Position, PropertyValue } from '../../core/model/Properties';
|
||||
import type { Position, PropertyValue, Vec2 } from '../../core/model/Properties';
|
||||
import { findAsset, findScene, findSceneObject } from '../../core/model/Project';
|
||||
import type { SceneObject } from '../../core/model/SceneObject';
|
||||
import { COMMON_PROPS, isCommonProp, type PropertyDef, schemaForAsset, VARIABLE_KINDS, type VariableKind } from '../../core/properties/PropertySchema';
|
||||
@@ -323,6 +324,41 @@ export class Inspector extends Panel {
|
||||
this.body.add(row.row);
|
||||
}
|
||||
|
||||
// Editor offset – where the object is *drawn* in the scene view, nothing else. Handy for
|
||||
// objects that sit on top of each other (stacked screens): pull them apart to work on them.
|
||||
this.body.add(new Label('EDITOR OFFSET (SCENE VIEW ONLY)', { style: 'title' }));
|
||||
for (const axis of ['x', 'y'] as const) {
|
||||
let original: Vec2 | undefined;
|
||||
const row = createFieldRow(
|
||||
{ key: `editorOffset${axis.toUpperCase()}`, label: `Offset ${axis.toUpperCase()}`, kind: 'number', default: 0, step: 1 },
|
||||
object.editorOffset[axis],
|
||||
{
|
||||
onInput: (value) => {
|
||||
const target = this.currentObject(sceneId, objectId);
|
||||
if (!target) return;
|
||||
if (!original) original = { ...target.editorOffset };
|
||||
target.editorOffset[axis] = Number(value);
|
||||
this.state.preview();
|
||||
},
|
||||
onChange: (value) => {
|
||||
const target = this.currentObject(sceneId, objectId);
|
||||
if (!target) return;
|
||||
const previous = original ?? { ...target.editorOffset };
|
||||
if (original) target.editorOffset = { ...original };
|
||||
original = undefined;
|
||||
this.state.execute(new SetEditorOffsetCommand(sceneId, objectId, { ...previous, [axis]: Number(value) }, previous));
|
||||
},
|
||||
},
|
||||
// Back to "drawn where it really is". No apply: the offset never leaves the scene object.
|
||||
() =>
|
||||
this.currentObject(sceneId, objectId)?.editorOffset[axis]
|
||||
? [{ label: 'Reset to 0', onSelect: () => this.resetEditorOffset(sceneId, objectId, axis) }]
|
||||
: [],
|
||||
);
|
||||
this.fields.set(`editorOffset${axis.toUpperCase()}`, row);
|
||||
this.body.add(row.row);
|
||||
}
|
||||
|
||||
// Asset properties (or behavior variables) with overrides. The common switch (Enabled)
|
||||
// is shown on its own, above the position – it exists for every type and is not a
|
||||
// "property of a sprite" in the same sense.
|
||||
@@ -557,6 +593,8 @@ export class Inspector extends Panel {
|
||||
this.fields.get('x')?.setValue(object.position.x);
|
||||
this.fields.get('y')?.setValue(object.position.y);
|
||||
this.fields.get('z')?.setValue(object.position.z);
|
||||
this.fields.get('editorOffsetX')?.setValue(object.editorOffset.x);
|
||||
this.fields.get('editorOffsetY')?.setValue(object.editorOffset.y);
|
||||
const values = resolveSceneObjectProps(asset, object);
|
||||
for (const def of schemaForAsset(asset)) this.fields.get(def.key)?.setValue(values[def.key] ?? def.default);
|
||||
this.markObjectRows(object, asset, templateLinkOf(this.state.project, scene, object));
|
||||
@@ -569,6 +607,8 @@ export class Inspector extends Panel {
|
||||
*/
|
||||
private markObjectRows(object: SceneObject, asset: Asset, link: TemplateLink | undefined): void {
|
||||
for (const axis of ['x', 'y', 'z'] as const) this.fields.get(axis)?.setModified(Boolean(link) && object.position[axis] !== link!.template.position[axis]);
|
||||
// The offset has one base only: no offset at all. Bold means "shown somewhere else than it is".
|
||||
for (const axis of ['x', 'y'] as const) this.fields.get(`editorOffset${axis.toUpperCase()}`)?.setModified(object.editorOffset[axis] !== 0);
|
||||
for (const def of schemaForAsset(asset)) {
|
||||
const deviates = link ? deviatesFromTemplate(object, link.template, def.key) : deviatesFromAsset(object, asset, def.key);
|
||||
this.fields.get(def.key)?.setModified(deviates);
|
||||
@@ -593,6 +633,13 @@ export class Inspector extends Panel {
|
||||
};
|
||||
}
|
||||
|
||||
/** Drops the editor offset on one axis (the row's ↺). */
|
||||
private resetEditorOffset(sceneId: string, objectId: string, axis: 'x' | 'y'): void {
|
||||
const object = this.currentObject(sceneId, objectId);
|
||||
if (!object || object.editorOffset[axis] === 0) return;
|
||||
this.state.execute(new SetEditorOffsetCommand(sceneId, objectId, { ...object.editorOffset, [axis]: 0 }));
|
||||
}
|
||||
|
||||
/** Whether the object sits somewhere else on `axis` than the container template says. */
|
||||
private positionMoved(sceneId: string, objectId: string, axis: 'x' | 'y' | 'z'): boolean {
|
||||
const object = this.currentObject(sceneId, objectId);
|
||||
|
||||
Reference in new issue
Block a user