Skip to content

Commit

Permalink
Add web rendered trail,remove crop
Browse files Browse the repository at this point in the history
  • Loading branch information
upgradeQ committed Jun 10, 2021
1 parent 9650127 commit 25001d5
Show file tree
Hide file tree
Showing 14 changed files with 1,427 additions and 122 deletions.
31 changes: 17 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
Fork by 3_4_700, original by upgradeQ
The main purpose of this fork is to be able to make a precise custom cursor, like a handdrawn arm holding a pen for artists

# OBS Studio Cursor skin
Selected source will follow mouse pointer.
Using [`obs_sceneitem_set_pos`](https://obsproject.com/docs/reference-scenes.html#c.obs_sceneitem_set_pos)
Expand All @@ -11,31 +8,27 @@ Using [`obs_sceneitem_set_pos`](https://obsproject.com/docs/reference-scenes.htm
# Limitations
- Multiple monitors setup will not work .
- If used in fullscreen apps, offset will appear.
- Current code only works for 1920x1080 res
# Usage
- Create a _source_ with desired cursor(e.g Image source or Media source).
- In scripts select _that_ source name.
- Make a group, add Display Capture, Window Capture
- Make a group, add Display Capture, Window Capture.

![img](https://i.imgur.com/CHuLwmp.png)

- To crop, crop the _group_, the size should still have the same ratio as your monitor even if you scale it
- To set offset/calibrate, use the Display Capture to see mouse and adjust it at Scripts (or use Tab/Shift+tab to navigate if in Window Capture to not move mouse). You have to do this every time you change the Group scale/move the Group
- To set offset/calibrate, use the Display Capture to see mouse and adjust it at Scripts (or use Tab/Shift+tab to navigate, if in Window Capture, to not move mouse). You have to do this every time you change the Group scale/move it

![img](https://user-images.githubusercontent.com/66927691/121442471-56133280-c9be-11eb-9bb4-ad12b2e4ebfb.jpg)

![img](https://user-images.githubusercontent.com/66927691/121442809-f23d3980-c9be-11eb-954f-c0e635e95d88.jpg)


- Test it: press Start, press Stop, tweak refresh rate.
# Crop auto update
Zoom or higlight.
- Create 2 display captures.
- Create crop filter with this name: `cropXY`.
- Check relative.
- Set Width and Height to relatively small numbers e.g : 64x64 .
- Image mask blend + color correction might be an option too.
- Run script,select this source as cursor source , check Update crop, click start.

# Web rendered mouse cursor trails
- Add browser source with mouse tracking local or online web page.
- Make sure to set resolution as your monitor (base)
- Fill all entries, check `Use browser source`

# Zoom
> Have you ever needed to zoom in on your screen to show some fine detail work,
Expand All @@ -53,6 +46,16 @@ They all have some level of transparency.
![img](https://i.imgur.com/8qoRU3i.png)
- green circle
![Imgur](https://i.imgur.com/s3jvZP5.png)

# On the Roadmap
- Visual indicator of mouse up/down state.
- Lua based shaders rendering (on mouse up, down, trail, etc...)
- Custom web page rendering (on mouse up, down, trail, etc...)

# Acknowledgments
- [`3_4_700`](https://github.com/34700) added offsets functionality for precise custom cursor(like a hand drawn arm holding a pen for artists)
- [`tholman/cursor-effects`](https://github.com/tholman/cursor-effects) - stock cursor trails

# Contribute
[Forks](https://help.github.com/articles/fork-a-repo) are a great way to contribute to a repository.
After forking a repository, you can send the original author a [pull request](https://help.github.com/articles/using-pull-requests)
18 changes: 18 additions & 0 deletions cursor_effects_ported/buble.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html>

<head>
<meta charset="utf-8">
<title>Buble cursor</title>
<script src="./cursor-effects-master/src/bubbleCursor.js"></script>
<style>
html, body {
height: 100%;
width: 100%;
padding: 0; margin: 0; /* reset the default stylesheet */
}
</style>
</head>
<body>
<script> new bubbleCursor(); </script>
</body>
</html>
150 changes: 150 additions & 0 deletions cursor_effects_ported/cursor-effects-master/src/bubbleCursor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
function bubbleCursor(options) {
let hasWrapperEl = options && options.element
let element = hasWrapperEl || document.body

let width = window.innerWidth
let height = window.innerHeight
let cursor = { x: width / 2, y: width / 2 }
let particles = []
let canvas, context

let canvImages = []

function init(wrapperEl) {
canvas = document.createElement("canvas")
context = canvas.getContext("2d")

canvas.style.top = "0px"
canvas.style.left = "0px"
canvas.style.pointerEvents = "none"

if (hasWrapperEl) {
canvas.style.position = "absolute"
element.appendChild(canvas)
canvas.width = element.clientWidth
canvas.height = element.clientHeight
} else {
canvas.style.position = "fixed"
document.body.appendChild(canvas)
canvas.width = width
canvas.height = height
}

bindEvents()
loop()
}

// Bind events that are needed
function bindEvents() {
element.addEventListener("mousemove", onMouseMove)
element.addEventListener("touchmove", onTouchMove)
element.addEventListener("touchstart", onTouchMove)
window.addEventListener("resize", onWindowResize)
}

function onWindowResize(e) {
width = window.innerWidth
height = window.innerHeight

if (hasWrapperEl) {
canvas.width = element.clientWidth
canvas.height = element.clientHeight
} else {
canvas.width = width
canvas.height = height
}
}

function onTouchMove(e) {
if (e.touches.length > 0) {
for (let i = 0; i < e.touches.length; i++) {
addParticle(
e.touches[i].clientX,
e.touches[i].clientY,
canvImages[Math.floor(Math.random() * canvImages.length)]
)
}
}
}

function onMouseMove(e) {
if (hasWrapperEl) {
const boundingRect = element.getBoundingClientRect()
cursor.x = e.clientX - boundingRect.left
cursor.y = e.clientY - boundingRect.top
} else {
cursor.x = e.clientX
cursor.y = e.clientY
}

addParticle(cursor.x, cursor.y)
}

function addParticle(x, y, img) {
particles.push(new Particle(x, y, img))
}

function updateParticles() {
context.clearRect(0, 0, width, height)

// Update
for (let i = 0; i < particles.length; i++) {
particles[i].update(context)
}

// Remove dead particles
for (let i = particles.length - 1; i >= 0; i--) {
if (particles[i].lifeSpan < 0) {
particles.splice(i, 1)
}
}
}

function loop() {
updateParticles()
requestAnimationFrame(loop)
}

function Particle(x, y, canvasItem) {
const lifeSpan = Math.floor(Math.random() * 60 + 60)
this.initialLifeSpan = lifeSpan //
this.lifeSpan = lifeSpan //ms
this.velocity = {
x: (Math.random() < 0.5 ? -1 : 1) * (Math.random() / 10),
y: -0.4 + Math.random() * -1,
}
this.position = { x: x, y: y }
this.canv = canvasItem

this.baseDimension = 4

this.update = function(context) {
this.position.x += this.velocity.x
this.position.y += this.velocity.y
this.velocity.x += ((Math.random() < 0.5 ? -1 : 1) * 2) / 75
this.velocity.y -= Math.random() / 600
this.lifeSpan--

const scale =
0.2 + (this.initialLifeSpan - this.lifeSpan) / this.initialLifeSpan

context.fillStyle = "#e6f1f7"
context.strokeStyle = "#3a92c5"
context.beginPath()
context.arc(
this.position.x - (this.baseDimension / 2) * scale,
this.position.y - this.baseDimension / 2,
this.baseDimension * scale,
0,
2 * Math.PI
)

context.stroke()
context.fill()

context.closePath()
}
}

init()
}
Loading

0 comments on commit 25001d5

Please sign in to comment.