-
Notifications
You must be signed in to change notification settings - Fork 263
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
5e Cone Area of Effect on Square Grid: "Template/Stencil" Method #4588
base: develop
Are you sure you want to change the base?
Conversation
Correct issue with scaling when drawing shapes. Was drawing in the ZonePoint space (0,0), (0, 1), etc. When I needed to draw in GridPoint space (100,100), (100, 200). Fix cone size and calculate theta instead of endpoint. There is an issue still with calculating the theta on the fly... The issue comes up when we zoom in and out while we are adjusting the angle. Add bounding boxes to the cone. Add logic to reduce cone into AOE squares in grid. Add logic to reduce cone into AOE squares in grid. Add shoelace formula for partially intersecting segments. Improve performance of painting. Instead of iterating over gridsquare, we split the candidate aoe vertically and horizontally and apply tests on the aoe before getting down to the grid size. The tests are more limited when looking at larger than grid size: It's either no intersection with the cone or full intersection... We can only evaluate the overlapping area against the threshold meaningfully at the grid square level. Add persisting of AOE when confirmed. Added dto and related usage in Drawable.java and implement builder in RightAngleConeTemplate.java. Also added some logic to not show the cone overlay when the template is "confirmed" and added to the layer... This is driven by the showOAEOverlay property in RightAngleConeTemplate.java, which is set to true when constructed without an id (i.e. in drawing mode) and false when given an id (i.e. confirmed and persisted into the campaign). I also fixed a minor bug with the behavior of the threshold which was doing the opposite of what is expected ( 90% threshold setting was actually 10%). Remove snapping to grid Use ZonePoint instead of CellPoint to determine radius more fluidly Remove useless comments Re-organize code Run spotlessApply
dbb32f0
to
f4f10fc
Compare
I think this is just a bad class name on my part 😆 I implemented what you sent, but goofed on the name. If you look for a call to `tan` you'll see the constants I have for the angles should match your description.
I can check again later though to be sure.
Any classname suggestions then? `IscoceleseTriangleWithBaseEqualsHeight` seems a little rough, but idk if something like 5eCone would fly?
…On Thu, Dec 28, 2023, at 12:54 AM, Reverend wrote:
Buuuut... 5e cones are not a right triangle. They are an isoceles triangle with base = height.
image.png (view on web) <https://github.com/RPTools/maptool/assets/45483160/47821e31-be07-4b35-bab7-bbdcff940356>
—
Reply to this email directly, view it on GitHub <#4588 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AON65K7FNYRXF7AXPRZ5GELYLUCQZAVCNFSM6AAAAABBD7T5OGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQNZQHA2DQNRQGM>.
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
// The definition of the cone is it is as wide as it is
// long, so the cone angle is tan inverse of 1/2, since
// if the length of the cone is 1, there is half it's
// length from the midpoint to the left and right edge
// of the base of the cone respectively...
public static double CONE_ANGLE = Math.atan2(0.5, 1.0);
// This is the ratio of the cone's side length to the
// length from the point of the cone to the midpoint of the
// base of the cone...
public static double CONE_SIDE_LENGTH_RATIO = 1 / Math.cos(CONE_ANGLE); |
Screencast.from.2023-12-28.13-38-16.webm |
It seems you use Affine Transforms purely to satisfy overrides and copied code.
|
Interesting point... I didn't really understand this component honestly.
Would the resulting code change then be: create static stencil at instantiation of the class then use the `radius` and `theta` to scale and rotate as those parameters change from mouse movement? I can also ignore re-renders if those parameters don't change...
Currently I create the stencil from scratch on each mouse movement event and evaluate it against the grid.
…On Fri, Dec 29, 2023, at 12:54 AM, Reverend wrote:
It seems you use Affine Transforms purely to satisfy overrides and copied code.
I wonder if it wouldn't be easier/faster to create a static Path2D once, then use affine rotate and scale to create the drawn triangle.
—
Reply to this email directly, view it on GitHub <#4588 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AON65KYR222GPD3UTQ46RPLYLZLIZAVCNFSM6AAAAABBD7T5OGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQNZRG42DQMZXGI>.
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
|
In 9666847 I tested this and the method of re-calculated the cone from scratch each time was faster, but really insignificantly so... Test results:
If there is any selection to be made, we should pick whichever has easier to understand logic between |
Thanks for doing the comparison. Don't think of it as insignificant, think of it as nearly half. |
#4873 might be related to the grid adjustment bug. It might not be anything related to your code |
Identify the Bug or Feature request
Relates to but does not fix #1276.
This PR implements a D&D 5e cone AoE on a Square Grid following the "Template" methodology (as opposed to the "Token" methodology).
Description of the Change
Create a new Template type called
TriangleTemplate
. The goal of this template is to match the cone's area of effect (see bellow quoted from SRD).From the perspective of the user, the way the new cone template works is:
During step 3, the user can hold control to move the origin like with all other templates. They can also hit control to cancel.
During step 3, the shape of the cone as per the SRD has its boundary drawn (this is to make the resulting area of effect clearer). The cone itself is compared against the grid to determine which grid cells are contained in the area of effect. The grid cells contained in the area of effect have a boundary drawn around them, and are also filled with the color of the drawing tools.
During step 4 the shape of the cone is discarded, and only the resulting area of effect is drawn into the grid.
Here is a screen recording of this feature in action. The jank (slowness and choppyness) is from my screencasting and not how it behaves in the app.
Technical Components
TriangleTemplateTool.java
ToolbarPanel.java
TriangleTemplate.java
TriangleTemplateDto
indrawing_dto.proto
fromDto
inDrawable.java
.TriangleTemplate
is the actual area of effect definition (it's parameters, how to draw it, etc.). The parameters are a startingvertex
, the direction ortheta
of the cone and theradius
of the cone. Thevertex
is in pixel space, since this template is not snapped to the grid for the drawing components, only the generated AOE is snapped to the grid. Thetheta
is a real number from [0,360) giving the angle of the cone. Theradius
is snapped to the size of the grid. It handles painting the AOE onto the grid. The most important method to understand is thepaint
method. This calculates the co-ordinates of the cone and the gridded bounding rectanglegridSnappedBoundingBox
(any grid square that could interesect with the cone is considered). ThegridSnappedBoundingBox
is added to a PriorityQueue which is used to iterate over candidate regions to establish if they should be in the AoE or not. The process is as follows as long as there is an entry in the Priority Queue:a. The Candidate AoE is a single Grid Square: In this case, use the Shoelace formula to determine if more than half of the Grid Square is covered by the Cone. If more than half is covered, include the candidate in the final AoE. The shoelace formula was selected since it is efficient compared with continuing to sub-divide the Grid down to the pixel level and testing the AoE. It also doesn't have any issues with granularity and doesn't require programming any further stopping conditions.
b. If the candidate AoE is not a single grid square, split the candidate AoE in 4 (2x2) and add each of the four resulting squares to the PriorityQueue. Splitting the candidates was chosen since it is more efficient than iterating over each grid square in
gridSnappedBoundingBox
, since we can short cicuit some of the AoE processing if we end up in1
or2
.TriangleTemplateTool
is fairly simple (although long). It is mostly method definitions copied fromRadiusTemplateTool
. This class handles the drawing state machine (are we drawing, is the CTRL key pressed or not, have we set the starting point, handle final mouse-click, etc.).Possible Drawbacks
Some stuff I might have overlooked:
Documentation Notes
Release Notes
This change is
WIP Components
Decide on toolbar icon.
Improve naming in code
Make "sensitivity" a parameter of the template so that if this becomes something we want to adjust through the UI we can implement that without changing the core functionality in the future.
Set the default sensitivity to 0.
Fix bugs with squares being left out.
Test performance of a static triangle scaled and rotated using AffineTransform.
Grid adjustment bug. The shape does not change when the grid is changed.
Fix how the name and icon look in the Draw Explorer tab.
Cleanup.
Open follow up issues (sensitivity adjustment, "token" method, "gridless" method [1])
[1]
This requires interacting with the tokens themselves which is not something templates currently do.