Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Symmetrical Drawing Mode in the Map Editor #19

Merged
merged 26 commits into from
May 19, 2024

Conversation

dkratz
Copy link
Contributor

@dkratz dkratz commented May 15, 2024

Description

Adds symmetrical drawing mode in the map editor.

Resolves #7

@@ -104,6 +106,22 @@ export default abstract class Vector {
return szudzik(this.x + 1, this.y + 1);
}

mirror(
mapSize: SizeVector,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is some repetition in this function, so maybe just destructure like { height, width }: SizeVector?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, since this function is only used sparely, I would probably prefer making it a standalone function in athena/lib or hera/editor/lib as like mirrorVector(vector: Vector, mirrorType: MirrorType).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -1,4 +1,6 @@
import sortBy from '@deities/hephaestus/sortBy.tsx';
import { DrawingMode } from '../../hera/editor/Types.tsx';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't import from hera in the athena package since athena also runs on the server without access to React. I think we need to define a VectorMirror (?) type with just 'horizontal' | 'vertical' | 'diagonal' and then use that as a base for DrawingMode in the editor types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be solved, since I moved vector.mirror inside hera: 349ef4c

hera/GameMap.tsx Outdated
@@ -62,6 +62,7 @@ import { resetBehavior, setBaseClass } from './behavior/Behavior.tsx';
import MenuBehavior from './behavior/Menu.tsx';
import NullBehavior from './behavior/NullBehavior.tsx';
import Cursor from './Cursor.tsx';
import MapEditorExtraCursors from './editor/MapEditorExtraCursors.tsx';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about calling it MapEditorMirrorCursors.tsx?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 430a4f7

Comment on lines 237 to 270
private putMultiple(
vectors: Vector[],
state: State,
actions: Actions,
editor: EditorState,
): StateLike | null {
let result: StateLike | null = null;
const players = Array.from(
new Set([...state.map.active, ...PlayerIDs]),
).slice(0, vectors.length);
vectors.forEach((vector, index) => {
const currentPlayerIndex = players.indexOf(
state.map.getCurrentPlayer().id,
);
const playerId =
players[
((currentPlayerIndex >= 0 ? currentPlayerIndex : 0) + index) %
players.length
];

const tempResult = this.put(
vector,
{ ...state, ...result },
actions,
editor,
playerId,
);
result = {
...(result ?? {}),
...tempResult,
};
});
return result;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is why more elegant than what I could have come up with. Nice!

}

return vectors.map((vector) => (
<Cursor key={vector.toString()} {...props} position={vector} />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just pass vector, toString is implicitly called.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypeScript doesn't like that:
Type 'Vector' is not assignable to type 'Key | null | undefined'.ts(2322)

drawingMode: DrawingMode,
mapSize: SizeVector,
) {
const vectors: Vector[] = [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Code style.

Suggested change
const vectors: Vector[] = [];
const vectors: Array<Vector> = [];

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated: b8ece22

Also opened #21

}
}

return vectors.filter((v) => !vector.equals(v));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I'm always trying to have descriptive variable names, even if it's obvious. In this case, I would probably rename vector to origin, and then rename v here to vector. That makes the code just slightly easier to read overall.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +251 to +255
const playerId =
players[
((currentPlayerIndex >= 0 ? currentPlayerIndex : 0) + index) %
players.length
];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not include 0 as 0 is the neutral unit type that can be rescued. Can you update it so it only uses one of the valid player ids except 0?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 257 to 267
const tempResult = this.put(
vector,
{ ...state, ...result },
actions,
editor,
playerId,
);
result = {
...(result ?? {}),
...tempResult,
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need the ?? {} as you can spread null.

Suggested change
const tempResult = this.put(
vector,
{ ...state, ...result },
actions,
editor,
playerId,
);
result = {
...(result ?? {}),
...tempResult,
};
const newState = this.put(
vector,
{ ...state, ...result },
actions,
editor,
playerId,
);
result = {
...(newState),
...tempResult,
};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think result had a different type at some point. Removed the null check: e9eaa9a

Some renaming: 387fe45

@cpojer
Copy link
Contributor

cpojer commented May 16, 2024

Thank you for the contribution, the implementation is so elegant and it feels magical already. Apologies that it took me a bit to get back to you as I'm at a conference right now. I left a few comments, but it's just small nits.

Replying to your comment on the issue here:

Do you have a preference on where to put the buttons? I was thinking of placing them below the "Playtest" button on the right side (vertically stacked).

I think that would look best too. I still need to think about the exact icons, but if you can get the layout ready I'll take another look and push some icons.

@@ -255,6 +256,51 @@ export default function DesignPanel({
return (
<Tick animationConfig={AnimationConfig}>
<Stack gap={24} vertical verticalPadding>
<Box center gap={32}>
{/* TODO(dkratz): Remove text and add selected state to buttons */}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can either use selected or selectedText on InlineLink. They are different active states for links. You can use the editor's drawing mode to compare the state.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done: bdf6ab5

@cpojer
Copy link
Contributor

cpojer commented May 16, 2024

On maps with odd width/height, cursor artifacts can be left behind like this:

CleanShot 2024-05-16 at 10 01 04@2x

Repro is just to draw randomly on the map for a bit and then the artifact cursors show up.

@dkratz
Copy link
Contributor Author

dkratz commented May 17, 2024

On maps with odd width/height, cursor artifacts can be left behind like this:

CleanShot 2024-05-16 at 10 01 04@2x

Repro is just to draw randomly on the map for a bit and then the artifact cursors show up.

This seems to happen in the horizontal-vertical mode by simply moving the mouse around (no need to draw).
Not memoizing MapEditorMirrorCurors fixes that issue (although I'm not quite sure why, not memoizing it should be fine though.).

hera/GameMap.tsx Outdated
Comment on lines 1733 to 1734
// TODO: adjust color
color="red"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cpojer PTAL

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'm just gong to leave them all red for now. It's easier to parse. Might change it in the future.

@dkratz dkratz requested a review from cpojer May 17, 2024 13:25
@dkratz dkratz marked this pull request as ready for review May 17, 2024 13:25
@cpojer
Copy link
Contributor

cpojer commented May 19, 2024

The problem with the "stuck" cursors was that getSymmetricalPositions sometimes return an array containing the same vector multiple times. I'm fixing that up.

@cpojer cpojer force-pushed the map-editor-symmetric-drawing branch from 0056017 to 9210f69 Compare May 19, 2024 04:44
@cpojer cpojer merged commit e893189 into nkzw-tech:main May 19, 2024
2 checks passed
@cpojer
Copy link
Contributor

cpojer commented May 19, 2024

Thank you, this is awesome, I'm very excited about this feature! The funds were sent to you. I'd love to see more contributions if you are working on any!

@dkratz
Copy link
Contributor Author

dkratz commented May 19, 2024

Nice, excited to have my first open source contribution merged :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature] Symmetrical Drawing Mode in the Map Editor
2 participants