-
Notifications
You must be signed in to change notification settings - Fork 8
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
Proof of concept: base classes for options, events, interactions #93
base: techdebt/imports
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am anticipating some push back against the use of interfaces over types here. When it comes to inheritance/sharing properties interfaces are by far the easier/cleaner approach. By leaning into inheritance we will be less likely to have inconsistencies in our type model
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is probably just my preference for functional programming over oop, but my assumption was that anything you can do w/ types you can do with interfaces. e.g.
interface X extends Y { foo: string, bar: string }
// same as
type X = Y & { foo: string, bar: string }
With the notable difference that types can express both intersections &
and unions |
. Typescript briefly notes the differences here, and honestly I like it that you can't mutate a type while you can mutate an interface (mutating an interface feels like a bug in waiting).
It's worth noting that the creator of Typescript also created C#. C#, like Java, is heavily oriented towards oop, but has also incorporated a lot of functional concepts on top. What if they both (and Typescript...) had just started with a simple functional pattern, avoided oop, and cut the language's surface area in half...?
import { Container, DisplayObject } from 'pixi.js' | ||
import { RenderObjectLifecycle } from '../types' | ||
|
||
export default abstract class RenderObject<T extends DisplayObject = DisplayObject> implements RenderObjectLifecycle { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RenderObject
- abstract class serves as a base for any display object in an app. i.e. Strokes, Icon, etc.
- creates a required structure for all display objects making them easy to manage in a generic way
- simple base methods can be overridden or enhanced in practice
import { Options, DefaultOptions, Viewport, Dimensions } from '../types/api' | ||
import { DEFAULT_OPTIONS, isNumber } from '../utils' | ||
|
||
export default class RendererOptions implements DefaultOptions { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RendererOptions
- straight forward class that manages and updates renderer options
- automatically applies defaults
- single instance that can be a shared as a dependency without losing reference to the object after updates
import { EventHandlers } from '../../types/api' | ||
import { EventSystem } from 'pixi.js' | ||
|
||
export default class ApplicationEvents { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ApplicationEvents
- similar to
RendererOptions
, this class will manage and update application events - can also manage other properties like the
EventSystem
for easy access in relevant classes
import Drag from './plugins/Drag' | ||
import Zoom from './plugins/Zoom' | ||
|
||
export default class InteractionManager { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
InteractionManager
- primarily for organization and usability
this:
this.renderer.dragInteraction.dragging
this.renderer.zoomInteraction.zooming
this.renderer.interactionObjectManager.mount(this.hitArea)
this.renderer.interaction
becomes this when you share the reference instead of the entire renderer:
this.interactions.isDragging
this.interactions.isZooming
this.interactions.manager.mount(this.hitArea)
this.interactions.container
import Interaction from '../Interaction' | ||
import HitArea from '../hitArea/HitArea' | ||
|
||
export default abstract class EventsManager extends Interaction { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EventsManager
- will be the base class for defining things like node events, viewport events, etc.
- simplifies the relationship between hit area + events
import { AllFederatedEventMap, Container, IHitArea } from 'pixi.js' | ||
import RenderObject from '../../RenderObject' | ||
|
||
export default class HitArea<T extends IHitArea = IHitArea> extends RenderObject<Container> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HitArea
- base class can be used on its own or extended to define a particular shape (circle, line, rect, etc.)
nothing in here is "plugged" in to the renderer yet, but this stands as a proof of concept for some structured base classes