diff --git a/source/GM-TE/GMTEBrush.class.st b/source/GM-TE/GMTEBrush.class.st index a97ea5c2..616c22cb 100644 --- a/source/GM-TE/GMTEBrush.class.st +++ b/source/GM-TE/GMTEBrush.class.st @@ -1,3 +1,6 @@ +" +A GMTEBrush is responsible for returning a set of indices that are selected by the user and selecting the interchangeable algorithm for the execution. +" Class { #name : #GMTEBrush, #superclass : #Object, @@ -9,7 +12,8 @@ Class { 'firstMatrixIndex', 'outputSet' ], - #category : #'GM-TE-UI' + #category : #'GM-TE-UI', + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 13:49' } { @@ -22,57 +26,61 @@ GMTEBrush class >> borderingOffsets [ ] { - #category : #forms, - #'squeak_changestamp' : 'JS 7/11/2024 15:40' + #category : #brushHelper, + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 14:03' } GMTEBrush >> calculateOffsetsForRadius: aRadius [ |offsets| offsets := OrderedCollection new. - (0-radius to: radius) do: [:dx | - (0-radius to: radius) do: [:dy | + (0-self radius to: self radius) do: [:dx | + (0-self radius to: self radius) do: [:dy | ((dx squared + dy squared) <= aRadius squared) ifTrue: [offsets add: dx @ dy]]]. - ^offsets + ^ offsets ] { #category : #accessing, - #'squeak_changestamp' : 'Valentin Teutschbein 7/6/2024 12:48' + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 13:40' } GMTEBrush >> currentBrush [ + ^ currentBrush ] { #category : #accessing, - #'squeak_changestamp' : 'Valentin Teutschbein 7/6/2024 12:48' + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 13:40' } -GMTEBrush >> currentBrush: anObject [ - currentBrush := anObject +GMTEBrush >> currentBrush: aBrush [ + + currentBrush := aBrush ] { #category : #accessing, - #'squeak_changestamp' : 'Valentin Teutschbein 7/9/2024 08:47' + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 13:41' } GMTEBrush >> currentMatrixIndex [ + ^ currentMatrixIndex ] { #category : #accessing, - #'squeak_changestamp' : 'Valentin Teutschbein 7/9/2024 08:47' + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 13:41' } -GMTEBrush >> currentMatrixIndex: anObject [ - currentMatrixIndex := anObject +GMTEBrush >> currentMatrixIndex: anIndex [ + + currentMatrixIndex := anIndex ] { - #category : #'as yet unclassified', - #'squeak_changestamp' : 'Valentin Teutschbein 7/11/2024 17:10' + #category : #execute, + #'squeak_changestamp' : 'JS 7/12/2024 16:50' } -GMTEBrush >> executeWithMatrixIndex: anIndex andLayer: aLayer [ +GMTEBrush >> executeWithIndex: anIndex andLayer: aLayer [ anIndex ifNil: [^ nil]. self currentMatrixIndex: anIndex. @@ -81,8 +89,8 @@ GMTEBrush >> executeWithMatrixIndex: anIndex andLayer: aLayer [ ] { - #category : #forms, - #'squeak_changestamp' : 'Valentin Teutschbein 7/11/2024 17:10' + #category : #brushes, + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 13:26' } GMTEBrush >> fillBrush [ @@ -95,51 +103,49 @@ GMTEBrush >> fillBrush [ self outputSet add: self currentMatrixIndex. visited at: self currentMatrixIndex y at: self currentMatrixIndex x put: true. - self fillDfsWithVisited: visited andIndex: self currentMatrixIndex andOriginTile: startTile andSet: self outputSet. + self fillDfsWithVisited: visited andIndex: self currentMatrixIndex andOriginTile: startTile. ^ self outputSet ] { - #category : #forms, - #'squeak_changestamp' : 'JS 7/11/2024 18:28' + #category : #brushHelper, + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 13:32' } -GMTEBrush >> fillDfsWithVisited: aVisitedMatrix andIndex: anIndex andOriginTile: anOriginTile andSet: aSet [ - self flag: 'REFACTOR!'. - +GMTEBrush >> fillDfsWithVisited: aVisitedMatrix andIndex: anIndex andOriginTile: anOriginTile [ + + | newIndex newTile | GMTEBrush borderingOffsets do: [:offset | - | newIndex newTile tilesNil tilesSame | newIndex := offset + anIndex. ((self layer inBounds: newIndex) and: [(aVisitedMatrix at: newIndex y at: newIndex x) isNil]) ifTrue:[ newTile := self layer at: newIndex y at: newIndex x. - tilesNil := (anOriginTile isNil) and: [newTile isNil]. - tilesSame := (anOriginTile isNil not and: [newTile isNil not]) and: [anOriginTile imageForm bits hash = newTile imageForm bits hash]. - - (tilesNil or: tilesSame) ifTrue: [ - aSet add: newIndex. + (self tile: anOriginTile equalsTile: newTile) ifTrue: [ + self outputSet add: newIndex. aVisitedMatrix at: newIndex y at: newIndex x put: true. - self fillDfsWithVisited: aVisitedMatrix andIndex: newIndex andOriginTile: anOriginTile andSet: aSet]]] + self fillDfsWithVisited: aVisitedMatrix andIndex: newIndex andOriginTile: anOriginTile]]] ] { #category : #accessing, - #'squeak_changestamp' : 'Valentin Teutschbein 7/9/2024 08:49' + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 13:41' } GMTEBrush >> firstMatrixIndex [ + ^ firstMatrixIndex ] { #category : #accessing, - #'squeak_changestamp' : 'Valentin Teutschbein 7/9/2024 08:49' + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 13:42' } -GMTEBrush >> firstMatrixIndex: anObject [ - firstMatrixIndex := anObject +GMTEBrush >> firstMatrixIndex: anIndex [ + + firstMatrixIndex := anIndex ] { - #category : #forms, + #category : #initialization, #'squeak_changestamp' : 'JS 7/11/2024 13:59' } GMTEBrush >> initialize [ @@ -150,34 +156,36 @@ GMTEBrush >> initialize [ { #category : #accessing, - #'squeak_changestamp' : 'Valentin Teutschbein 7/6/2024 14:51' + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 13:42' } GMTEBrush >> layer [ + ^ layer ] { #category : #accessing, - #'squeak_changestamp' : 'Valentin Teutschbein 7/6/2024 14:51' + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 13:42' } -GMTEBrush >> layer: anObject [ - layer := anObject +GMTEBrush >> layer: aLayer [ + + layer := aLayer ] { - #category : #forms, - #'squeak_changestamp' : 'Valentin Teutschbein 7/11/2024 17:11' + #category : #brushes, + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 13:53' } GMTEBrush >> lineBrush [ self resetOutputSet. - self firstMatrixIndex ifNil: [^nil]. + self firstMatrixIndex ifNil: [^ nil]. - (self rasterizeLineBetweenAStart: self firstMatrixIndex andAnEnd: self currentMatrixIndex) do: [:point | + (self rasterizeLineBetweenStart: self firstMatrixIndex andEnd: self currentMatrixIndex) do: [:index | (self calculateOffsetsForRadius: self offsetCorrectedRadius) do: [:offset | - self outputSet add: (point + offset)]]. + self outputSet add: (index + offset)]]. - ^(self outputSet) + ^ self outputSet ] @@ -193,18 +201,20 @@ GMTEBrush >> offsetCorrectedRadius [ { #category : #accessing, - #'squeak_changestamp' : 'Valentin Teutschbein 7/9/2024 21:18' + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 13:43' } GMTEBrush >> outputSet [ + ^ outputSet ] { #category : #accessing, - #'squeak_changestamp' : 'Valentin Teutschbein 7/9/2024 21:18' + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 13:43' } -GMTEBrush >> outputSet: anObject [ - outputSet := anObject +GMTEBrush >> outputSet: aSet [ + + outputSet := aSet ] { @@ -218,15 +228,15 @@ GMTEBrush >> radius [ { #category : #accessing, - #'squeak_changestamp' : 'Valentin Teutschbein 7/11/2024 17:15' + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 13:43' } -GMTEBrush >> radius: aNumber [ +GMTEBrush >> radius: aRadius [ - radius := aNumber + radius := aRadius ] { - #category : #forms, + #category : #brushes, #'squeak_changestamp' : 'Valentin Teutschbein 7/11/2024 17:09' } GMTEBrush >> radiusBrush [ @@ -239,62 +249,64 @@ GMTEBrush >> radiusBrush [ ] { - #category : #forms, - #'squeak_changestamp' : 'JS 7/11/2024 18:26' + #category : #brushHelper, + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 13:52' } -GMTEBrush >> rasterizeLineBetweenAStart: aStartPoint andAnEnd: anEndPoint [ +GMTEBrush >> rasterizeLineBetweenStart: aStartIndex andEnd: anEndIndex [ "implementation of Bresenhams Line Algorithm" - | linePointsCollection deltaX deltaY stepX stepY error error2 x y | + | lineIndexCollection deltaX deltaY stepX stepY error error2 x y index | - self flag: 'todo: method extraction? - Ich glaube geht schlecht'. + self flag: 'repeat formatting'. - deltaX := (anEndPoint x - aStartPoint x) abs. - deltaY := (anEndPoint y - aStartPoint y) abs. - stepX := (aStartPoint x < anEndPoint x) ifTrue: [1] ifFalse: [-1]. - stepY := (aStartPoint y < anEndPoint y) ifTrue: [1] ifFalse: [-1]. + deltaX := (anEndIndex x - aStartIndex x) abs. + deltaY := (anEndIndex y - aStartIndex y) abs. + stepX := (aStartIndex x < anEndIndex x) ifTrue: [1] ifFalse: [-1]. + stepY := (aStartIndex y < anEndIndex y) ifTrue: [1] ifFalse: [-1]. error := deltaX - deltaY. - x := aStartPoint x. - y := aStartPoint y. + x := aStartIndex x. + y := aStartIndex y. - linePointsCollection := OrderedCollection new. + lineIndexCollection := OrderedCollection new. - [ - | point | - point := x @ y. - linePointsCollection add: point. - (x = anEndPoint x and: [y = anEndPoint y]) ifTrue: [ - ^linePointsCollection]. + [ index := x @ y. + lineIndexCollection add: index. + (x = anEndIndex x and: [y = anEndIndex y]) ifTrue: [^ lineIndexCollection]. error2 := 2 * error. (error2 > (0 - deltaY)) ifTrue: [ error := error - deltaY. x := x + stepX]. (error2 < deltaX) ifTrue: [ error := error + deltaX. - y := y + stepY] - ] repeat + y := y + stepY]] repeat ] { - #category : #forms, - #'squeak_changestamp' : 'JS 7/11/2024 17:34' + #category : #brushes, + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 13:57' } GMTEBrush >> rectangleBrush [ + | endCol endRow startCol startRow | self resetOutputSet. self firstMatrixIndex ifNil: [^ nil]. - (self currentMatrixIndex x min: self firstMatrixIndex x) to: (self currentMatrixIndex x max: self firstMatrixIndex x) do: [:row | - (self currentMatrixIndex y min: self firstMatrixIndex y) to: (self currentMatrixIndex y max: self firstMatrixIndex y) do: [:col | - self outputSet add: (row @ col)]]. + startRow := (self currentMatrixIndex x min: self firstMatrixIndex x). + endRow := (self currentMatrixIndex x max: self firstMatrixIndex x). + startCol := (self currentMatrixIndex y min: self firstMatrixIndex y). + endCol := (self currentMatrixIndex y max: self firstMatrixIndex y). + + startRow to: endRow do: [:row | + startCol to: endCol do: [:col | + self outputSet add: (row@col)]]. ^ self outputSet ] { - #category : #select, + #category : #brushHelper, #'squeak_changestamp' : 'JS 7/11/2024 13:43' } GMTEBrush >> resetOutputSet [ @@ -337,3 +349,16 @@ GMTEBrush >> selectRectangleBrush [ self currentBrush: [self rectangleBrush] ] + +{ + #category : #brushHelper, + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 13:31' +} +GMTEBrush >> tile: aTile equalsTile: anotherTile [ + + | tilesNil tilesSame | + tilesNil := (aTile isNil) and: [anotherTile isNil]. + tilesSame := (aTile isNil not and: [anotherTile isNil not]) and: [aTile imageForm bits hash = anotherTile imageForm bits hash]. + + ^ (tilesNil or: [tilesSame]) +] diff --git a/source/GM-TE/GMTEEditTilesCommand.class.st b/source/GM-TE/GMTEEditTilesCommand.class.st index 1972bc86..3d5d2879 100644 --- a/source/GM-TE/GMTEEditTilesCommand.class.st +++ b/source/GM-TE/GMTEEditTilesCommand.class.st @@ -2,6 +2,7 @@ Class { #name : #GMTEEditTilesCommand, #superclass : #GMTECommand, #instVars : [ + 'editor', 'tileMap', 'previousSprites', 'currentSprites' @@ -47,6 +48,22 @@ GMTEEditTilesCommand >> do [ self placeTilesFromList: self currentSprites ] +{ + #category : #accessing, + #'squeak_changestamp' : 'Alex M 7/12/2024 17:12' +} +GMTEEditTilesCommand >> editor [ + ^ editor +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'Alex M 7/12/2024 17:12' +} +GMTEEditTilesCommand >> editor: anObject [ + editor := anObject +] + { #category : #initialization, #'squeak_changestamp' : 'Alex M 6/28/2024 02:45' diff --git a/source/GM-TE/GMTEEditor.class.st b/source/GM-TE/GMTEEditor.class.st index 877965ac..fedd96b3 100644 --- a/source/GM-TE/GMTEEditor.class.st +++ b/source/GM-TE/GMTEEditor.class.st @@ -1061,7 +1061,7 @@ GMTEEditor >> exportMenu [ { #category : #'input handling', - #'squeak_changestamp' : 'mcjj 7/11/2024 15:57' + #'squeak_changestamp' : 'mcjj 7/12/2024 00:19' } GMTEEditor >> filterEvent: aKeyboardEvent for: anObject [ | key | @@ -1069,22 +1069,15 @@ GMTEEditor >> filterEvent: aKeyboardEvent for: anObject [ aKeyboardEvent isKeystroke ifFalse: [^ aKeyboardEvent]. - key := aKeyboardEvent key. - + key := aKeyboardEvent keyCharacter. + aKeyboardEvent commandKeyPressed ifTrue: [ - aKeyboardEvent shiftPressed - ifTrue: [ - key caseOf: { - [$Z] -> [self redo]. - } otherwise: [^ aKeyboardEvent "no hit"]. - ^ aKeyboardEvent ignore "hit"] - ifFalse: [ - key caseOf: { - [$Z] -> [self undo]. - [$Y] -> [self redo]. - [$R] -> [self rotateSelectedTile]. - } otherwise: [^ aKeyboardEvent "no hit"]. - ^ aKeyboardEvent ignore "hit"]]. + key caseOf: { + [$z] -> [self undo]. + [$y] -> [self redo]. + [$r] -> [self rotateSelectedTile]. + } otherwise: [^ aKeyboardEvent "no hit"]. + ^ aKeyboardEvent ignore "hit"]. ^ aKeyboardEvent "no hit" ] @@ -1791,12 +1784,14 @@ GMTEEditor >> resetSelectedLayers [ { #category : #TODO, - #'squeak_changestamp' : 'Alex M 6/25/2024 18:26' + #'squeak_changestamp' : 'mcjj 7/11/2024 17:52' } GMTEEditor >> rotateSelectedTile [ self selectedTile: (self selectedTile rotateBy: #right centerAt: (self selectedTile extent / 2)). - self tileMap tileSelectionSet highlightImage: self selectedTile + self tileMap tileSelectionSet removeAllHighlightings. + self tileMap tileSelectionSet highlightImage: self selectedTile. + self tileMap tileSelectionSet applyAllHighlightings ] { diff --git a/source/GM-TE/GMTEEditorTileMap.class.st b/source/GM-TE/GMTEEditorTileMap.class.st index e5d34777..33e3a0a6 100644 --- a/source/GM-TE/GMTEEditorTileMap.class.st +++ b/source/GM-TE/GMTEEditorTileMap.class.st @@ -1,3 +1,6 @@ +" +A GMTEEditorTileMap is a Tilemap that can only be found in the editor or as an exported .morph file. It provides the additional methods for i/o compared to the regular tilemap. +" Class { #name : #GMTEEditorTileMap, #superclass : #GMTETileMap, @@ -7,7 +10,8 @@ Class { 'previousTileStates', 'currentTileChanges' ], - #category : #'GM-TE-TileMap' + #category : #'GM-TE-TileMap', + #'squeak_changestamp' : 'JS 7/12/2024 17:04' } { @@ -23,43 +27,49 @@ GMTEEditorTileMap class >> tileWidth: aWidth tileHeight: aHeight padding: aPaddi ] { - #category : #TODO, - #'squeak_changestamp' : 'Valentin Teutschbein 7/5/2024 17:07' + #category : #accessing, + #'squeak_changestamp' : 'JS 7/12/2024 16:55' } -GMTEEditorTileMap >> calculateTileCollectionFromPosition: aPos andLayer: aLayer [ - - | index rawCollection resultCollection | - self flag: 'remove method'. - index := self tileIndexFromPosition: aPos. - index ifNil: [^ nil]. - rawCollection := OrderedCollection new. - resultCollection := OrderedCollection new. - self flag: 'Add different algos'. - rawCollection add: (self tileMatrixStack layer: aLayer at: index y at: index x). - self halt. - - rawCollection add: (self tileMatrixStack layer: aLayer at: index y at: ((index x)+1)). - rawCollection do: [:t | - t ifNil: [resultCollection add: (self generateTileAtlayer: aLayer x: index x y: index y stack: self tileMatrixStack tileType: GMTETile)]. - t ifNotNil: [resultCollection add: t] - ]. - ^ resultCollection +GMTEEditorTileMap >> brush [ + + ^ self model brush ] { #category : #accessing, - #'squeak_changestamp' : 'Alex M 6/28/2024 19:28' + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 14:15' } GMTEEditorTileMap >> currentTileChanges [ + ^ currentTileChanges ] { #category : #accessing, - #'squeak_changestamp' : 'Alex M 6/28/2024 19:28' + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 14:18' } -GMTEEditorTileMap >> currentTileChanges: anObject [ - currentTileChanges := anObject +GMTEEditorTileMap >> currentTileChanges: aTileDictionary [ + + currentTileChanges := aTileDictionary +] + +{ + #category : #updating, + #'squeak_changestamp' : 'Alex M 7/12/2024 17:16' +} +GMTEEditorTileMap >> deleteTiles: anIndexSet inLayer: aLayer [ + "delete tiles from editable matrix stack at given indices" + + | tile | + anIndexSet do: [:c | + ((self tileMatrixStack layer: aLayer) inBounds: c) ifTrue: [ + tile := self tileMatrixStack layer: aLayer at: c y at: c x. + tile ifNotNil: [ + self savePreviousImageFromIndex: c inLayer: aLayer. + tile abandon. + self tileMatrixStack layer: aLayer at: c y at: c x put: nil. + self saveNewImageFromIndex: c inLayer: aLayer. + self model savedSinceModified: false]]] ] { @@ -89,6 +99,22 @@ GMTEEditorTileMap >> handlesMouseOver: anEvent [ ^ true ] +{ + #category : #updating, + #'squeak_changestamp' : 'JS 7/12/2024 15:15' +} +GMTEEditorTileMap >> highlightTilesFromIndices: anIndexSet [ + + | hoveredHighlightingTile | + self tileSelectionSet clearAllHighlightings. + anIndexSet ifNil: [^ nil]. + + (anIndexSet select: [:c | + (self tileMatrixStack layer: self model selectedLayers anyOne) inBounds: c]) do: [:t | + hoveredHighlightingTile := self highlightingTileFromIndex: t. + hoveredHighlightingTile ifNotNil: [self tileSelectionSet highlightTile: hoveredHighlightingTile]] +] + { #category : #initialization, #'squeak_changestamp' : 'Ivo Zilkenat 7/12/2024 17:04' @@ -114,100 +140,118 @@ GMTEEditorTileMap >> model [ { #category : #accessing, - #'squeak_changestamp' : 'TW 6/22/2024 01:25' + #'squeak_changestamp' : 'JS 7/12/2024 16:25' } -GMTEEditorTileMap >> model: anObject [ +GMTEEditorTileMap >> model: aModel [ - model := anObject + model := aModel ] { #category : #'event handling', - #'squeak_changestamp' : 'JS 7/11/2024 14:13' + #'squeak_changestamp' : 'JS 7/12/2024 16:50' } GMTEEditorTileMap >> mouseDown: anEvent [ - "Implements placement of tiles" + "prepare the brush for next operation on self" | selectedIndex | - self flag: 'refactor; method extraction for "Add tiles to layer" to minimize redundancy with mouseMove?'. - self model singleLayerSelected ifFalse: [^nil]. + self model singleLayerSelected ifFalse: [^ nil]. + selectedIndex := self tileIndexFromPosition: anEvent position. - self model brush firstMatrixIndex: selectedIndex. - self model brush executeWithMatrixIndex: selectedIndex andLayer: (self tileMatrixStack layer: self model selectedLayers anyOne). - anEvent yellowButtonPressed ifTrue: [self tileSelectionSet highlightImage: nil]. + self brush firstMatrixIndex: selectedIndex. - ^ true + self brush executeWithIndex: selectedIndex andLayer: (self tileMatrixStack layer: self selectedLayers anyOne). + anEvent yellowButtonPressed ifTrue: [self tileSelectionSet highlightImage: nil] ] { #category : #'event handling', - #'squeak_changestamp' : 'Ivo Zilkenat 7/11/2024 17:18' + #'squeak_changestamp' : 'JS 7/12/2024 16:27' } GMTEEditorTileMap >> mouseLeave: anEvent [ - - self tileSelectionSet clearAllHighlightings. - ^ true + self tileSelectionSet clearAllHighlightings ] { #category : #'event handling', - #'squeak_changestamp' : 'Ivo Zilkenat 7/12/2024 16:52' + #'squeak_changestamp' : 'Ivo Zilkenat 7/12/2024 17:20' } GMTEEditorTileMap >> mouseMove: anEvent [ - "Implements highlighting of tiles when hovering" + "implements highlighting of tiles when hovering" - | hoveredTileHighlighting activeLayer selectedCoordinates | + | activeLayer selectedIndices currentIndex | super mouseMove: anEvent. anEvent shiftPressed ifTrue: [^ nil]. self model singleLayerSelected ifFalse: [^ nil]. - activeLayer := self model selectedLayers anyOne. - selectedCoordinates := self model brush executeWithMatrixIndex: (self tileIndexFromPosition: anEvent position) andLayer: (self tileMatrixStack layer: activeLayer). - (anEvent redButtonPressed or: [anEvent yellowButtonPressed]) ifFalse: [self model brush resetOutputSet]. - self tileSelectionSet clearAllHighlightings. + activeLayer := self tileMatrixStack layer: self model selectedLayers anyOne. + currentIndex := self tileIndexFromPosition: anEvent position. + + selectedIndices := self brush executeWithIndex: currentIndex andLayer: activeLayer. - selectedCoordinates ifNil: [^ nil]. + (anEvent redButtonPressed or: [anEvent yellowButtonPressed]) ifFalse: [self brush resetOutputSet]. - (selectedCoordinates select: [:c | - (self tileMatrixStack layer: activeLayer) inBounds: c]) do: [:t | - hoveredTileHighlighting := self highlightingTileFromIndex: t. - hoveredTileHighlighting ifNotNil: [self tileSelectionSet highlightTile: hoveredTileHighlighting]] + self highlightTilesFromIndices: selectedIndices ] { #category : #'event handling', - #'squeak_changestamp' : 'mcjj 7/11/2024 16:20' + #'squeak_changestamp' : 'JS 7/12/2024 16:28' } GMTEEditorTileMap >> mouseUp: anEvent [ + "apply brush operation on tilemap" + + | selectedIndices | + self brush firstMatrixIndex: nil. + + selectedIndices := self brush outputSet asCollection. + + self updateTiles: selectedIndices inLayer: self selectedLayers anyOne FromEvent: anEvent. + self brush resetOutputSet. - | indicesToAdd activeLayer | - self model brush firstMatrixIndex: nil. - indicesToAdd := self model brush outputSet. - activeLayer := self model selectedLayers anyOne. - self updateTiles: (indicesToAdd asCollection) inLayer: activeLayer FromEvent: anEvent. - self model brush resetOutputSet. (self previousTileStates isEmpty) ifFalse: [self saveTileEditChanges]. - self tileSelectionSet clearAllHighlightings. - self tileSelectionSet highlightImage: (self model selectedTile) + self tileSelectionSet + clearAllHighlightings; + highlightImage: (self model selectedTile) ] +{ + #category : #updating, + #'squeak_changestamp' : 'Alex M 7/12/2024 17:15' +} +GMTEEditorTileMap >> placeTiles: aCoordinateCollection inLayer: aLayer [ + "add currently selected tile (model) to editable matrix stack at given indices" + + | tile | + aCoordinateCollection do: [:c | + self savePreviousImageFromIndex: c inLayer: aLayer. + ((self tileMatrixStack layer: aLayer) inBounds: c) ifTrue: [ + tile := self tileMatrixStack layer: aLayer at: c y at: c x. + tile ifNil: [tile := self generateTileAtlayer: aLayer x: c x y: c y stack: tileMatrixStack tileType: GMTETile]. + self model selectedTile ifNotNil: [tile updateSprite: self model selectedTile]. + self saveNewImageFromIndex: c inLayer: aLayer. + self model savedSinceModified: false]] +] + { #category : #accessing, - #'squeak_changestamp' : 'Alex M 6/28/2024 19:44' + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 14:16' } GMTEEditorTileMap >> previousTileStates [ + ^ previousTileStates ] { #category : #accessing, - #'squeak_changestamp' : 'Alex M 6/28/2024 19:44' + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 14:18' } -GMTEEditorTileMap >> previousTileStates: anObject [ - previousTileStates := anObject +GMTEEditorTileMap >> previousTileStates: aTileDictionary [ + + previousTileStates := aTileDictionary ] { @@ -222,12 +266,12 @@ GMTEEditorTileMap >> rescaleMap [ ] { - #category : #TODO, - #'squeak_changestamp' : 'Alex M 7/3/2024 23:50' + #category : #updating, + #'squeak_changestamp' : 'JS 7/12/2024 16:31' } GMTEEditorTileMap >> resetLayers: aSet [ - | layer | + | layer | aSet do: [:layerIndex | layer := self tileMatrixStack layer: layerIndex. layer withIndicesDo: [:tile :y :x | @@ -250,73 +294,52 @@ GMTEEditorTileMap >> resetTileEditChanges [ { #category : #'command processing', - #'squeak_changestamp' : 'Alex M 7/6/2024 01:31' + #'squeak_changestamp' : 'JS 7/12/2024 16:34' } -GMTEEditorTileMap >> saveNewImageFromCoordinate: aCoordinate inLayer: aLayer [ - | tile | - - tile := self tileMatrixStack layer: aLayer at: aCoordinate y at: aCoordinate x. +GMTEEditorTileMap >> saveNewImageFromIndex: anIndex inLayer: aLayer [ + | tile | + tile := self tileMatrixStack layer: aLayer at: anIndex y at: anIndex x. + tile - ifNil: [self currentTileChanges at: {aCoordinate x. aCoordinate y. aLayer} put: nil] - ifNotNil: [self currentTileChanges at: {aCoordinate x. aCoordinate y. aLayer} put: tile fullResolutionSprite] + ifNil: [self currentTileChanges at: {anIndex x. anIndex y. aLayer} put: nil] + ifNotNil: [self currentTileChanges at: {anIndex x. anIndex y. aLayer} put: tile fullResolutionSprite] ] { #category : #'command processing', - #'squeak_changestamp' : 'Alex M 7/6/2024 01:34' + #'squeak_changestamp' : 'JS 7/12/2024 16:40' } -GMTEEditorTileMap >> saveNewImageFromPosition: aPosition inLayer: aLayer [ - - self saveNewImageFromCoordinate: (self tileIndexFromPosition: aPosition) inLayer: aLayer -] +GMTEEditorTileMap >> savePreviousImageFromIndex: anIndex inLayer: aLayer [ -{ - #category : #'command processing', - #'squeak_changestamp' : 'Alex M 7/6/2024 01:54' -} -GMTEEditorTileMap >> savePreviousImageFromCoordinate: aCoordinate inLayer: aLayer [ - | tile | - - tile := self tileMatrixStack layer: aLayer at: aCoordinate y at: aCoordinate x. + | tile | + tile := self tileMatrixStack layer: aLayer at: anIndex y at: anIndex x. tile - ifNil: [self previousTileStates at: {aCoordinate x. aCoordinate y. aLayer} ifAbsentPut: nil] - ifNotNil: [self previousTileStates at: {aCoordinate x. aCoordinate y. aLayer} ifAbsentPut: tile fullResolutionSprite] + ifNil: [self previousTileStates at: {anIndex x. anIndex y. aLayer} ifAbsentPut: nil] + ifNotNil: [self previousTileStates at: {anIndex x. anIndex y. aLayer} ifAbsentPut: tile fullResolutionSprite] ] { #category : #'command processing', - #'squeak_changestamp' : 'Valentin Teutschbein 7/6/2024 11:46' + #'squeak_changestamp' : 'JS 7/12/2024 16:43' } -GMTEEditorTileMap >> savePreviousImageFromMatrixCoordinate: aCoordinate inLayer: aLayer [ - | tile | - - tile := self tileMatrixStack layer: aLayer at: aCoordinate y at: aCoordinate x. +GMTEEditorTileMap >> saveTileEditChanges [ - tile - ifNil: [self previousTileStates at: {aCoordinate x. aCoordinate y. aLayer} ifAbsentPut: nil] - ifNotNil: [self previousTileStates at: {aCoordinate x. aCoordinate y. aLayer} ifAbsentPut: tile fullResolutionSprite] -] - -{ - #category : #'command processing', - #'squeak_changestamp' : 'Valentin Teutschbein 7/6/2024 11:58' -} -GMTEEditorTileMap >> savePreviousImageFromPosition: aPosition inLayer: aLayer [ + | command | + command := GMTEEditTilesCommand previousTiles: self previousTileStates currentTiles: self currentTileChanges tilemap: self. - self savePreviousImageFromCoordinate: (self tileIndexFromPosition: aPosition) inLayer: aLayer + self model addCommand: command. + self resetTileEditChanges ] { - #category : #'command processing', - #'squeak_changestamp' : 'JS 7/11/2024 14:07' + #category : #accessing, + #'squeak_changestamp' : 'JS 7/12/2024 16:55' } -GMTEEditorTileMap >> saveTileEditChanges [ +GMTEEditorTileMap >> selectedLayers [ - self - model addCommand: (GMTEEditTilesCommand previousTiles: self previousTileStates currentTiles: self currentTileChanges tilemap: self). - self resetTileEditChanges. + ^ self model selectedLayers ] { @@ -330,58 +353,25 @@ GMTEEditorTileMap >> tileSelectionSet [ { #category : #accessing, - #'squeak_changestamp' : 'TW 6/22/2024 01:25' + #'squeak_changestamp' : 'Valentin Teutschbein 7/12/2024 14:16' } -GMTEEditorTileMap >> tileSelectionSet: anObject [ +GMTEEditorTileMap >> tileSelectionSet: aSet [ - tileSelectionSet := anObject + tileSelectionSet := aSet ] { #category : #updating, - #'squeak_changestamp' : 'Alex M 6/25/2024 18:08' + #'squeak_changestamp' : 'Alex M 7/12/2024 17:14' } -GMTEEditorTileMap >> updateTileSprite: aTile [ - "Helper function to apply sprite from tile selection to aTile" - - self model selectedTile ifNotNil: [aTile updateSprite: self model selectedTile] -] - -{ - #category : #updating, - #'squeak_changestamp' : 'Alex M 7/11/2024 17:39' -} -GMTEEditorTileMap >> updateTiles: aCoordinateCollection inLayer: aLayer FromEvent: anEvent [ - "Add currently selected tile (model) to editable matrix stack at mouse position" - | tile | - self flag: 'refactor'. +GMTEEditorTileMap >> updateTiles: anIndexSet inLayer: aLayer FromEvent: anEvent [ + + | validLeftClick validRightClick | (self tileIndexFromPosition: anEvent position) ifNil: [^ nil]. - (anEvent redButtonChanged and: [self model selectedTile notNil]) - ifTrue: [ - aCoordinateCollection do: [:c | - self savePreviousImageFromMatrixCoordinate: c inLayer: aLayer. - ((self tileMatrixStack layer: aLayer) inBounds: c) ifTrue: [ - tile := self tileMatrixStack layer: aLayer at: c y at: c x. - tile - ifNil: [ tile := self generateTileAtlayer: aLayer x: c x y: c y stack: tileMatrixStack tileType: GMTETile]. - self updateTileSprite: tile. - self saveNewImageFromPosition: tile position inLayer: aLayer] - ]. - self model savedSinceModified: false]. - (anEvent yellowButtonChanged) - ifTrue: [ - aCoordinateCollection do: [:c | - | tilePos | - ((self tileMatrixStack layer: aLayer) inBounds: c) ifTrue: [ - tile := self tileMatrixStack layer: aLayer at: c y at: c x. - tile - ifNotNil: [ - self savePreviousImageFromMatrixCoordinate: c inLayer: aLayer. - tilePos := tile position. - tile abandon. - self tileMatrixStack layer: aLayer at: c y at: c x put: nil. - self saveNewImageFromPosition: tilePos inLayer: aLayer. - self model savedSinceModified: false]. - ] - ]] + + validLeftClick := anEvent redButtonChanged and: [self model selectedTile notNil]. + validRightClick := anEvent yellowButtonChanged. + + validLeftClick ifTrue: [self placeTiles: anIndexSet inLayer: aLayer]. + validRightClick ifTrue: [self deleteTiles: anIndexSet inLayer: aLayer]. ] diff --git a/source/GM-TE/GMTETileSelectionSet.class.st b/source/GM-TE/GMTETileSelectionSet.class.st index 51ad30b8..44228e7d 100644 --- a/source/GM-TE/GMTETileSelectionSet.class.st +++ b/source/GM-TE/GMTETileSelectionSet.class.st @@ -7,6 +7,17 @@ Class { #category : #'GM-TE-TileMap' } +{ + #category : #highlighting, + #'squeak_changestamp' : 'mcjj 7/11/2024 17:11' +} +GMTETileSelectionSet >> applyAllHighlightings [ + + self do: [:tile | + self applyHighlightingVisuals: tile] + +] + { #category : #highlighting, #'squeak_changestamp' : 'Ivo Zilkenat 6/24/2024 11:51' @@ -71,6 +82,17 @@ GMTETileSelectionSet >> initialize: n [ ] +{ + #category : #highlighting, + #'squeak_changestamp' : 'mcjj 7/11/2024 17:52' +} +GMTETileSelectionSet >> removeAllHighlightings [ + "Remove applied highlightings if any" + + self do: [:tile | + self removeHighlightingVisuals: tile] +] + { #category : #highlighting, #'squeak_changestamp' : 'Ivo Zilkenat 6/24/2024 11:51' diff --git a/source/GM-TE/GMTETilemapSizeCommand.class.st b/source/GM-TE/GMTETilemapSizeCommand.class.st index fe18b4f0..fe683543 100644 --- a/source/GM-TE/GMTETilemapSizeCommand.class.st +++ b/source/GM-TE/GMTETilemapSizeCommand.class.st @@ -2,7 +2,6 @@ Class { #name : #GMTETilemapSizeCommand, #superclass : #GMTEEditTilesCommand, #instVars : [ - 'editor', 'method', 'prevSize', 'newSize', @@ -34,22 +33,6 @@ GMTETilemapSizeCommand >> do [ self editor perform: self method with: self newSize ] -{ - #category : #accessing, - #'squeak_changestamp' : 'Alex M 7/1/2024 18:00' -} -GMTETilemapSizeCommand >> editor [ - ^ editor -] - -{ - #category : #accessing, - #'squeak_changestamp' : 'Alex M 7/1/2024 18:00' -} -GMTETilemapSizeCommand >> editor: anObject [ - editor := anObject -] - { #category : #accessing, #'squeak_changestamp' : 'Alex M 7/1/2024 18:48' diff --git a/testMapFile.morph b/testMapFile.morph index 14d6c90c..3c046b80 100644 Binary files a/testMapFile.morph and b/testMapFile.morph differ