Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
leanmendoza committed Nov 28, 2024
1 parent cf41aed commit efb824c
Show file tree
Hide file tree
Showing 13 changed files with 294 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"--async-stack-traces"
],
"args": [
"${fileBasename}",
"${file}",
"--verbose",
"--no-cache",
"-i"
Expand Down
81 changes: 78 additions & 3 deletions packages/@dcl/ecs/src/systems/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,20 @@ export interface PointerEventsSystem {
*/
removeOnPointerUp(entity: Entity): void

/**
* @public
* Remove the callback for onPointerHoverEnter event
* @param entity - Entity where the callback was attached
*/
removeOnPointerHoverEnter(entity: Entity): void

/**
* @public
* Remove the callback for onPointerHoverLeave event
* @param entity - Entity where the callback was attached
*/
removeOnPointerHoverLeave(entity: Entity): void

/**
* @internal
* Execute callback when the user clicks the entity.
Expand Down Expand Up @@ -88,6 +102,28 @@ export interface PointerEventsSystem {
* @param opts - Opts to trigger Feedback and Button
*/
onPointerUp(entity: Entity, cb: EventSystemCallback, opts?: Partial<EventSystemOptions>): void

/**
* @public
* Execute callback when the user place the pointer over the entity
* @param pointerData - Entity to attach the callback - Opts to trigger Feedback and Button
* @param cb - Function to execute when click fires
*/
onPointerHoverEnter(
pointerData: { entity: Entity; opts?: Partial<EventSystemOptions> },
cb: EventSystemCallback
): void

/**
* @public
* Execute callback when the user take the pointer out of the entity
* @param pointerData - Entity to attach the callback - Opts to trigger Feedback and Button
* @param cb - Function to execute when click fires
*/
onPointerHoverLeave(
pointerData: { entity: Entity; opts?: Partial<EventSystemOptions> },
cb: EventSystemCallback
): void
}

/**
Expand All @@ -100,7 +136,9 @@ export function createPointerEventsSystem(engine: IEngine, inputSystem: IInputSy
enum EventType {
Click,
Down,
Up
Up,
HoverEnter,
HoverLeave
}
type EventMapType = Map<EventType, { cb: EventSystemCallback; opts: EventSystemOptions }>

Expand Down Expand Up @@ -135,6 +173,10 @@ export function createPointerEventsSystem(engine: IEngine, inputSystem: IInputSy
function getPointerEvent(eventType: EventType) {
if (eventType === EventType.Up) {
return PointerEventType.PET_UP
} else if (eventType === EventType.HoverLeave) {
return PointerEventType.PET_HOVER_LEAVE
} else if (eventType === EventType.HoverEnter) {
return PointerEventType.PET_HOVER_ENTER
}
return PointerEventType.PET_DOWN
}
Expand Down Expand Up @@ -164,7 +206,12 @@ export function createPointerEventsSystem(engine: IEngine, inputSystem: IInputSy
checkNotThenable(cb(command.up), 'Click event returned a thenable. Only synchronous functions are allowed')
}

if (eventType === EventType.Down || eventType === EventType.Up) {
if (
eventType === EventType.Down ||
eventType === EventType.Up ||
eventType === EventType.HoverEnter ||
eventType === EventType.HoverLeave
) {
const command = inputSystem.getInputCommand(opts.button, getPointerEvent(eventType), entity)
if (command) {
checkNotThenable(cb(command), 'Event handler returned a thenable. Only synchronous functions are allowed')
Expand Down Expand Up @@ -198,6 +245,24 @@ export function createPointerEventsSystem(engine: IEngine, inputSystem: IInputSy
setPointerEvent(entity, PointerEventType.PET_UP, options)
}

const onPointerHoverEnter: PointerEventsSystem['onPointerHoverEnter'] = (...args) => {
const [data, cb] = args
const { entity, opts } = data
const options = getDefaultOpts(opts)
removeEvent(entity, EventType.HoverEnter)
getEvent(entity).set(EventType.HoverEnter, { cb, opts: options })
setPointerEvent(entity, PointerEventType.PET_HOVER_ENTER, options)
}

const onPointerHoverLeave: PointerEventsSystem['onPointerHoverLeave'] = (...args) => {
const [data, cb] = args
const { entity, opts } = data
const options = getDefaultOpts(opts)
removeEvent(entity, EventType.HoverLeave)
getEvent(entity).set(EventType.HoverLeave, { cb, opts: options })
setPointerEvent(entity, PointerEventType.PET_HOVER_LEAVE, options)
}

return {
removeOnClick(entity: Entity) {
removeEvent(entity, EventType.Click)
Expand All @@ -211,6 +276,14 @@ export function createPointerEventsSystem(engine: IEngine, inputSystem: IInputSy
removeEvent(entity, EventType.Up)
},

removeOnPointerHoverEnter(entity: Entity) {
removeEvent(entity, EventType.HoverEnter)
},

removeOnPointerHoverLeave(entity: Entity) {
removeEvent(entity, EventType.HoverLeave)
},

onClick(value, cb) {
const { entity } = value
const options = getDefaultOpts(value.opts)
Expand All @@ -223,6 +296,8 @@ export function createPointerEventsSystem(engine: IEngine, inputSystem: IInputSy
},

onPointerDown,
onPointerUp
onPointerUp,
onPointerHoverEnter,
onPointerHoverLeave
}
}
14 changes: 14 additions & 0 deletions packages/@dcl/playground-assets/etc/playground-assets.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,8 @@ export type EntityComponents = {
uiDropdown: PBUiDropdown;
onMouseDown: Callback;
onMouseUp: Callback;
onMouseEnter: Callback;
onMouseLeave: Callback;
};

// @public (undocumented)
Expand Down Expand Up @@ -1558,6 +1560,8 @@ export interface LastWriteWinElementSetComponentDefinition<T> extends BaseCompon
export type Listeners = {
onMouseDown?: Callback;
onMouseUp?: Callback;
onMouseEnter?: Callback;
onMouseLeave?: Callback;
};

// @public (undocumented)
Expand Down Expand Up @@ -3313,13 +3317,23 @@ export interface PointerEventsSystem {
}, cb: EventSystemCallback): void;
// @deprecated (undocumented)
onPointerDown(entity: Entity, cb: EventSystemCallback, opts?: Partial<EventSystemOptions>): void;
onPointerHoverEnter(pointerData: {
entity: Entity;
opts?: Partial<EventSystemOptions>;
}, cb: EventSystemCallback): void;
onPointerHoverLeave(pointerData: {
entity: Entity;
opts?: Partial<EventSystemOptions>;
}, cb: EventSystemCallback): void;
onPointerUp(pointerData: {
entity: Entity;
opts?: Partial<EventSystemOptions>;
}, cb: EventSystemCallback): void;
// @deprecated (undocumented)
onPointerUp(entity: Entity, cb: EventSystemCallback, opts?: Partial<EventSystemOptions>): void;
removeOnPointerDown(entity: Entity): void;
removeOnPointerHoverEnter(entity: Entity): void;
removeOnPointerHoverLeave(entity: Entity): void;
removeOnPointerUp(entity: Entity): void;
}

Expand Down
4 changes: 3 additions & 1 deletion packages/@dcl/react-ecs/src/components/Button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ function getButtonProps(props: UiButtonProps) {
*/
/* @__PURE__ */
export function Button(props: UiButtonProps) {
const { uiTransform, uiBackground, onMouseDown, onMouseUp, ...otherProps } = props
const { uiTransform, uiBackground, onMouseDown, onMouseUp, onMouseEnter, onMouseLeave, ...otherProps } = props
const buttonProps = getButtonProps(props)
const uiBackgroundProps = parseUiBackground({
...buttonProps.uiBackground,
Expand Down Expand Up @@ -64,6 +64,8 @@ export function Button(props: UiButtonProps) {
<entity
onMouseDown={!!props.disabled ? undefined : onMouseDown}
onMouseUp={!!props.disabled ? undefined : onMouseUp}
onMouseEnter={!!props.disabled ? undefined : onMouseEnter}
onMouseLeave={!!props.disabled ? undefined : onMouseLeave}
uiTransform={uiTransformProps}
uiText={textProps}
uiBackground={uiBackgroundProps}
Expand Down
6 changes: 4 additions & 2 deletions packages/@dcl/react-ecs/src/components/Dropdown/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@ function parseUiDropdown(props: UiDropdownProps): PBUiDropdown {
*/
/* @__PURE__ */
export function Dropdown(props: UiDropdownProps) {
const { uiTransform, uiBackground, onMouseDown, onMouseUp, ...otherProps } = props
const { uiTransform, uiBackground, onMouseDown, onMouseUp, onMouseEnter, onMouseLeave, ...otherProps } = props
const dropdownProps = parseUiDropdown(otherProps)
const commonProps = parseProps({
uiTransform,
uiBackground,
onMouseDown,
onMouseUp
onMouseUp,
onMouseEnter,
onMouseLeave
})
return <entity {...commonProps} uiDropdown={dropdownProps} />
}
6 changes: 4 additions & 2 deletions packages/@dcl/react-ecs/src/components/Input/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,15 @@ function parseUiInput(props: Partial<UiInputProps>): PBUiInput {
* @category Component
*/ /* @__PURE__ */
export function Input(props: EntityPropTypes & Partial<UiInputProps>) {
const { uiTransform, uiBackground, onMouseDown, onMouseUp, ...otherProps } = props
const { uiTransform, uiBackground, onMouseDown, onMouseUp, onMouseEnter, onMouseLeave, ...otherProps } = props
const inputProps = parseUiInput(otherProps)
const commonProps = parseProps({
uiTransform,
uiBackground,
onMouseDown,
onMouseUp
onMouseUp,
onMouseEnter,
onMouseLeave
})
return <entity {...commonProps} uiInput={inputProps} />
}
6 changes: 4 additions & 2 deletions packages/@dcl/react-ecs/src/components/Label/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ export { scaleFontSize } from './utils'

/* @__PURE__ */
export function Label(props: EntityPropTypes & UiLabelProps) {
const { uiTransform, uiBackground, onMouseDown, onMouseUp, ...uiTextProps } = props
const { uiTransform, uiBackground, onMouseDown, onMouseUp, onMouseEnter, onMouseLeave, ...uiTextProps } = props

const commonProps = parseProps({
uiTransform,
uiBackground,
onMouseDown,
onMouseUp
onMouseUp,
onMouseEnter,
onMouseLeave
})
const { font, textAlign, fontSize, textWrap, ...textProps } = uiTextProps
const uiText: PBUiText = {
Expand Down
8 changes: 7 additions & 1 deletion packages/@dcl/react-ecs/src/components/listeners/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,17 @@ export type Listeners = {
onMouseDown?: Callback
/** triggered on mouse up event */
onMouseUp?: Callback
/** triggered on mouse hover event */
onMouseEnter?: Callback
/** triggered on mouse leave event */
onMouseLeave?: Callback
}

const listeners: Listeners = {
onMouseDown: undefined,
onMouseUp: undefined
onMouseUp: undefined,
onMouseEnter: undefined,
onMouseLeave: undefined
}
const listenersKey = Object.keys(listeners)

Expand Down
2 changes: 2 additions & 0 deletions packages/@dcl/react-ecs/src/react-ecs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ export type EntityComponents = {
uiDropdown: PBUiDropdown
onMouseDown: Callback
onMouseUp: Callback
onMouseEnter: Callback
onMouseLeave: Callback
}

/**
Expand Down
44 changes: 35 additions & 9 deletions packages/@dcl/react-ecs/src/reconciler/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ import { componentKeys, isNotUndefined, noopConfig, propsChanged } from './utils
function getPointerEnum(pointerKey: keyof Listeners): PointerEventType {
const pointers: { [key in keyof Required<Listeners>]: PointerEventType } = {
onMouseDown: PointerEventType.PET_DOWN,
onMouseUp: PointerEventType.PET_UP
onMouseUp: PointerEventType.PET_UP,
onMouseEnter: PointerEventType.PET_HOVER_ENTER,
onMouseLeave: PointerEventType.PET_HOVER_LEAVE
}
return pointers[pointerKey]
}
Expand Down Expand Up @@ -80,13 +82,20 @@ export function createReconciler(
upsertComponent(instance, props as { rightOf: number; parent: number }, 'uiTransform')
}

function upsertListener(instance: Instance, update: Changes<keyof Pick<Listeners, 'onMouseDown' | 'onMouseUp'>>) {
function upsertListener(
instance: Instance,
update: Changes<keyof Pick<Listeners, 'onMouseDown' | 'onMouseUp' | 'onMouseEnter' | 'onMouseLeave'>>
) {
if (update.type === 'delete' || !update.props) {
clickEvents.get(instance.entity)?.delete(getPointerEnum(update.component))
if (update.component === 'onMouseDown') {
pointerEvents.removeOnPointerDown(instance.entity)
} else if (update.component === 'onMouseUp') {
pointerEvents.removeOnPointerUp(instance.entity)
} else if (update.component === 'onMouseEnter') {
pointerEvents.removeOnPointerHoverEnter(instance.entity)
} else if (update.component === 'onMouseLeave') {
pointerEvents.removeOnPointerHoverLeave(instance.entity)
}
return
}
Expand All @@ -101,13 +110,30 @@ export function createReconciler(
if (alreadyHasPointerEvent) return

const pointerEventSystem =
update.component === 'onMouseDown' ? pointerEvents.onPointerDown : pointerEvents.onPointerUp
pointerEventSystem(instance.entity, () => pointerEventCallback(instance.entity, pointerEvent), {
button: InputAction.IA_POINTER,
// We add this showFeedBack so the pointerEventSystem creates a PointerEvent component with our entity
// This is needed for the renderer to know which entities are clickeables
showFeedback: true
})
update.component === 'onMouseDown'
? pointerEvents.onPointerDown
: update.component === 'onMouseUp'
? pointerEvents.onPointerUp
: update.component === 'onMouseEnter'
? pointerEvents.onPointerHoverEnter
: update.component === 'onMouseLeave'
? pointerEvents.onPointerHoverLeave
: undefined

if (pointerEventSystem !== undefined) {
pointerEventSystem(
{
entity: instance.entity,
opts: {
button: InputAction.IA_POINTER,
// We add this showFeedBack so the pointerEventSystem creates a PointerEvent component with our entity
// This is needed for the renderer to know which entities are clickeables
showFeedback: true
}
},
() => pointerEventCallback(instance.entity, pointerEvent)
)
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions packages/@dcl/react-ecs/src/reconciler/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ const entityComponent: EntityComponents = {
uiTransform: undefined as any,
onMouseDown: undefined as any,
onMouseUp: undefined as any,
onMouseEnter: undefined as any,
onMouseLeave: undefined as any,
uiInput: undefined as any,
uiDropdown: undefined as any
}
Expand Down
Loading

0 comments on commit efb824c

Please sign in to comment.