@@ -18,7 +18,12 @@ import {
1818 type SpriteAssetSpec ,
1919} from '../model/types' ;
2020import { createEmptyProject , createEmptyGameScene } from '../model/emptyProject' ;
21- import { deriveWorldUnitsFromNaturalPixels , normalizeProjectPixelsPerUnit } from '../model/projectPixelScale' ;
21+ import {
22+ deriveWorldSpriteSize ,
23+ deriveWorldUnitsFromNaturalPixels ,
24+ getProjectPixelsPerUnit ,
25+ normalizeProjectPixelsPerUnit ,
26+ } from '../model/projectPixelScale' ;
2227import { validateProjectSpec , validateSceneSpec } from '../model/validation' ;
2328import { resolveEntityDefaults } from '../model/entityDefaults' ;
2429import { applyGroupArrangeLayout , applyGroupGridLayout , applyGroupGridLayoutPreserveMembers , inferGroupGridLayout , type GroupGridLayout } from './formationLayout' ;
@@ -2198,6 +2203,46 @@ function recordHistoryForAction(stateBefore: EditorState, stateAfter: EditorStat
21982203 } ;
21992204}
22002205
2206+ function reapplyProjectPixelScaleToMatchingSprites (
2207+ previousProject : ProjectSpec ,
2208+ nextProject : ProjectSpec ,
2209+ ) : ProjectSpec {
2210+ const previousPixelsPerUnit = getProjectPixelsPerUnit ( previousProject ) ;
2211+ const nextPixelsPerUnit = getProjectPixelsPerUnit ( nextProject ) ;
2212+ if ( previousPixelsPerUnit === nextPixelsPerUnit ) return nextProject ;
2213+
2214+ let scenesChanged = false ;
2215+ const scenes = Object . fromEntries (
2216+ Object . entries ( nextProject . scenes ) . map ( ( [ sceneId , scene ] ) => {
2217+ let entitiesChanged = false ;
2218+ const entities = Object . fromEntries (
2219+ Object . entries ( scene . entities ) . map ( ( [ entityId , entity ] ) => {
2220+ const resolved = resolveEntityDefaults ( entity ) ;
2221+ if ( ! resolved . asset ) return [ entityId , entity ] ;
2222+
2223+ const previousWorldSize = deriveWorldSpriteSize ( previousProject , resolved . asset ) ;
2224+ const nextWorldSize = deriveWorldSpriteSize ( nextProject , resolved . asset ) ;
2225+ if ( ! previousWorldSize || ! nextWorldSize ) return [ entityId , entity ] ;
2226+ if ( resolved . width !== previousWorldSize . width || resolved . height !== previousWorldSize . height ) return [ entityId , entity ] ;
2227+
2228+ entitiesChanged = true ;
2229+ return [ entityId , {
2230+ ...entity ,
2231+ width : nextWorldSize . width ,
2232+ height : nextWorldSize . height ,
2233+ } ] ;
2234+ } ) ,
2235+ ) ;
2236+
2237+ if ( ! entitiesChanged ) return [ sceneId , scene ] ;
2238+ scenesChanged = true ;
2239+ return [ sceneId , { ...scene , entities } ] ;
2240+ } ) ,
2241+ ) as ProjectSpec [ 'scenes' ] ;
2242+
2243+ return scenesChanged ? { ...nextProject , scenes } : nextProject ;
2244+ }
2245+
22012246function applyAction ( state : EditorState , action : EditorAction ) : EditorState {
22022247 switch ( action . type ) {
22032248 case 'initialize' :
@@ -2262,7 +2307,7 @@ function applyAction(state: EditorState, action: EditorAction): EditorState {
22622307 && typeof action . publishTitle !== 'string'
22632308 && ( typeof state . project . publishTitle !== 'string' || state . project . publishTitle . trim ( ) . length === 0 )
22642309 ) ;
2265- const nextProject : ProjectSpec = {
2310+ const nextProjectDraft : ProjectSpec = {
22662311 ...state . project ,
22672312 ...( typeof action . title === 'string' ? { title : action . title } : { } ) ,
22682313 ...( typeof action . pixelsPerUnit === 'number'
@@ -2275,6 +2320,9 @@ function applyAction(state: EditorState, action: EditorAction): EditorState {
22752320 : { } ) ,
22762321 ...( typeof action . publishGithubPagesRepo === 'string' ? { publishGithubPagesRepo : action . publishGithubPagesRepo } : { } ) ,
22772322 } ;
2323+ const nextProject = typeof action . pixelsPerUnit === 'number'
2324+ ? reapplyProjectPixelScaleToMatchingSprites ( state . project , nextProjectDraft )
2325+ : nextProjectDraft ;
22782326 return { ...state , project : nextProject , dirty : true , error : undefined , projectRootEditing : false } ;
22792327 }
22802328 case 'set-theme-mode' :
0 commit comments