@aspiresys/visor 1.2.5 → 1.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/matcher.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Region } from "./types";
2
2
  export declare function loadTemplate(path: string): Promise<any>;
3
+ export declare function loadScreen(path: string): Promise<any>;
3
4
  export declare function matchTemplate(screen: any, template: any, confidence?: number): Region | null;
4
5
  export declare function findAllMatches(screen: any, template: any, confidence?: number): Region[];
package/dist/matcher.js CHANGED
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.loadTemplate = loadTemplate;
7
+ exports.loadScreen = loadScreen;
7
8
  exports.matchTemplate = matchTemplate;
8
9
  exports.findAllMatches = findAllMatches;
9
10
  const fs_1 = __importDefault(require("fs"));
@@ -27,6 +28,16 @@ async function loadTemplate(path) {
27
28
  templateCache.set(path, template);
28
29
  return template.clone();
29
30
  }
31
+ async function loadScreen(path) {
32
+ (0, logger_1.log)(`[SCREEN] Loading: ${path}`);
33
+ const buffer = fs_1.default.readFileSync(path);
34
+ const png = pngjs_1.PNG.sync.read(buffer);
35
+ return cv.matFromImageData({
36
+ data: png.data,
37
+ width: png.width,
38
+ height: png.height,
39
+ });
40
+ }
30
41
  function resizeTemplate(template, scale) {
31
42
  const resized = new cv.Mat();
32
43
  const newWidth = Math.max(1, Math.floor(template.cols * scale));
@@ -5,25 +5,107 @@
5
5
  <link rel="stylesheet" href="styles.css" />
6
6
  </head>
7
7
  <body>
8
- <h1>🔍 VISOR INSPECTOR </h1>
9
- <br>
10
- <div class="toolbar">
11
- <button id="captureBtn"> Capture </button>
12
- <button id="saveBtn"> Save Template </button>
13
- <button id="loadTemplateBtn"> Load Template </button>
14
- <button id="testMatchBtn"> Test Match </button>
8
+ <div class="container">
9
+ <header class="header">
10
+ <h3>VISOR INSPECTOR</h3>
11
+ </header>
12
+
13
+ <section class="controls-section">
14
+ <div class="toolbar">
15
+ <button id="captureBtn" class="btn btn-primary">
16
+ <span class="btn-icon">📸</span> Capture Screen
17
+ </button>
18
+ <button id="saveBtn" class="btn btn-secondary">
19
+ <span class="btn-icon">💾</span> Save Template
20
+ </button>
21
+ <button id="loadTemplateBtn" class="btn btn-secondary">
22
+ <span class="btn-icon">📂</span> Load Template
23
+ </button>
24
+ <button id="testMatchBtn" class="btn btn-accent">
25
+ <span class="btn-icon">✓</span> Test Match
26
+ </button>
27
+ <div class="controls-grid">
28
+ <div class="control-group">
29
+ <div class="input-wrapper">
30
+ <span class="input-hint">Confidence</span>
31
+ <input
32
+ id="confidenceInput"
33
+ type="number"
34
+ min="0"
35
+ max="1"
36
+ step="0.01"
37
+ value="0.8"
38
+ />
39
+ <span class="input-hint">(0.0 - 1.0)</span>
40
+ </div>
41
+ </div>
42
+ </div>
43
+ </div>
44
+ </section>
45
+
46
+ <section class="canvas-section">
47
+ <h3 class="section-title">Current Capture</h3>
48
+ <canvas id="screenCanvas" class="canvas"></canvas>
49
+ </section>
50
+
51
+ <section class="template-section">
52
+ <h3 class="section-title">Template Management</h3>
53
+ <div class="template-grid">
54
+ <div class="template-info">
55
+ <p><strong>Current Template:</strong></p>
56
+ <span id="currentTemplate" class="template-status">None</span>
57
+ </div>
58
+ <img id="templatePreview" class="template-preview" />
59
+ </div>
60
+
61
+ <h3 class="section-title">
62
+ Match Result
63
+ </h3>
64
+ <div id="matchStatus"
65
+ class="match-status">
66
+ No Match Tested
67
+ </div>
68
+ <div class="match-details">
69
+ <div class="match-row">
70
+ <span class="match-label">
71
+ Confidence
72
+ </span>
73
+ <span id="resultConfidence"
74
+ class="match-value">
75
+
76
+ </span>
77
+ </div>
78
+ <div class="match-row">
79
+ <span class="match-label">
80
+ Position
81
+ </span>
82
+ <span class="match-value">
83
+ X:
84
+ <span id="resultX">—</span>
85
+ |
86
+
87
+ Y:
88
+ <span id="resultY">—</span>
89
+ </span>
90
+ </div>
91
+ <div class="match-row">
92
+ <span class="match-label">
93
+ Size
94
+ </span>
95
+ <span class="match-value">
96
+ W:
97
+ <span id="resultWidth">—</span>
98
+
99
+ |
100
+
101
+ H:
102
+ <span id="resultHeight">—</span>
103
+ </span>
104
+ </div>
105
+ </div>
106
+ </section>
15
107
  </div>
16
- <label> Confidence </label>
17
- <input id="confidenceInput" type="number" min="0" max="1" step="0.01" value="0.8" />
18
- <br>
19
- <br>
20
- <canvas id="screenCanvas"></canvas>
21
- <hr>
22
- <h3> Template </h3>
23
- <div> Current Template: <span id="currentTemplate"> None </span>
24
- </div>
25
- <img id="templatePreview" width="300" />
26
- <div id="matchResult"></div>
108
+
27
109
  <script src="./src/renderer.js"></script>
28
110
  </body>
29
- </html>
111
+ </html>
package/inspector/main.js CHANGED
@@ -133,8 +133,8 @@ ipcMain.handle("test-match",
133
133
  async (event, data) => {
134
134
  console.log("Test Match IPC", data);
135
135
  const capturePath = path.join(__dirname, "assets", "capture.png");
136
- const screen = await visorMatcher.loadTemplate(capturePath);
137
- const template = await visorMatcher.loadTemplate(data.templatePath);
136
+ const screen = await visorMatcher.loadScreen(capturePath);
137
+ const template = await visorMatcher.loadScreen(data.templatePath);
138
138
  const result = visorMatcher
139
139
  .matchTemplate(
140
140
  screen,
@@ -71,6 +71,8 @@ canvas.addEventListener("mousemove",
71
71
  canvas.width,
72
72
  canvas.height
73
73
  );
74
+ ctx.strokeStyle = "red";
75
+ ctx.lineWidth = 2;
74
76
  ctx.strokeRect(
75
77
  displayStartX,
76
78
  displayStartY,
@@ -127,48 +129,48 @@ saveBtn.addEventListener("click",
127
129
  }
128
130
  );
129
131
 
130
- testMatchBtn.addEventListener("click",
131
- async () => {
132
- if(!selectedTemplatePath){
133
- alert("Please load or save a template first.");
134
- return;
135
- }
136
- const confidence = parseFloat(confidenceInput.value);
137
- if (
138
- isNaN(confidence) ||
139
- confidence < 0 ||
140
- confidence > 1
141
- ) {
142
- alert("Confidence must be between 0 and 1");
143
- return;
144
- }
145
- const result = await window.visor.testMatch({
146
- templatePath: selectedTemplatePath,
147
- confidence: confidence
148
- });
149
- if (!result) {
150
- matchResult.innerHTML = "Match Not Found";
151
- return;
152
- }
153
- matchResult.innerHTML =
154
- `
155
- Confidence:
156
- ${result.confidence}
157
- <br>
158
- X:
159
- ${result.x}
160
- <br>
161
- Y:
162
- ${result.y}
163
- <br>
164
- width:
165
- ${result.width}
166
- <br>
167
- height:
168
- ${result.height}
169
- `;
170
- }
171
- );
132
+ testMatchBtn.addEventListener("click", async () => {
133
+ if (!selectedTemplatePath) {
134
+ alert("Please load or save a template first.");
135
+ return;
136
+ }
137
+
138
+ const confidence = parseFloat(confidenceInput.value);
139
+ if (isNaN(confidence) || confidence < 0 || confidence > 1) {
140
+ alert("Confidence must be between 0 and 1");
141
+ return;
142
+ }
143
+
144
+ const result = await window.visor.testMatch({
145
+ templatePath: selectedTemplatePath,
146
+ confidence: confidence
147
+ });
148
+ console.log(
149
+ "Match Result:",
150
+ result
151
+ );
152
+
153
+ if (!result) {
154
+ document.getElementById("matchStatus").textContent = "✗ Match Not Found";
155
+ document.getElementById('resultConfidence').textContent = "—";
156
+ document.getElementById('resultX').textContent = "—";
157
+ document.getElementById('resultY').textContent = "—";
158
+ document.getElementById('resultWidth').textContent = "—";
159
+ document.getElementById('resultHeight').textContent = "—";
160
+ return;
161
+ }
162
+ const updateMatchResults = (data) => {
163
+ document.getElementById("matchStatus").textContent = "✓ Match Found";
164
+ document.getElementById('resultConfidence').textContent = data.confidence;
165
+ document.getElementById('resultX').textContent = data.x;
166
+ document.getElementById('resultY').textContent = data.y;
167
+ document.getElementById('resultWidth').textContent = data.width;
168
+ document.getElementById('resultHeight').textContent = data.height;
169
+ };
170
+
171
+ updateMatchResults(result);
172
+ });
173
+
172
174
 
173
175
  loadTemplateBtn.addEventListener("click",
174
176
  async () => {
@@ -1,53 +1,410 @@
1
+ * {
2
+ margin: 0;
3
+ padding: 0;
4
+ box-sizing: border-box;
5
+ }
6
+
7
+ .spacer {
8
+ flex: 1;
9
+ }
10
+
11
+ .match-status {
12
+ padding: 8px;
13
+ border: 1px solid #444;
14
+ border-radius: 6px;
15
+ margin-bottom: 10px;
16
+ font-weight: bold;
17
+
18
+ }
19
+ .match-details {
20
+ display: flex;
21
+ flex-direction: column;
22
+ gap: 6px;
23
+ }
24
+
25
+ .match-row {
26
+ display: flex;
27
+ justify-content: space-between;
28
+ padding: 4px 0;
29
+ }
30
+
31
+ .match-label {
32
+ color: #999;
33
+ font-size: 0.9em;
34
+ }
35
+
36
+ .match-value {
37
+ color: #00d4ff;
38
+ font-family: Consolas,
39
+ monospace;
40
+
41
+ }
42
+
1
43
  body {
2
- background: #1e1e1e;
3
- color: #d4d4d4;
4
- font-family: Segoe UI, sans-serif;
5
- margin: 20px;
44
+ background: linear-gradient(135deg, #0f0f0f 0%, #1a1a2e 100%);
45
+ color: #e0e0e0;
46
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
47
+ line-height: 1.6;
48
+ min-height: 100vh;
6
49
  }
7
50
 
8
- h1 {
9
- color: #4fc3f7;
10
- border-bottom: 2px solid #333;
11
- padding-bottom: 10px;
51
+ .container {
52
+ max-width: 1200px;
53
+ margin: 0 auto;
54
+ padding: 12px;
12
55
  }
13
56
 
14
- button {
15
- background: #2d2d30;
16
- color: white;
17
- border: 1px solid #4fc3f7;
18
- padding: 8px 14px;
19
- margin-right: 8px;
20
- cursor: pointer;
57
+ /* HEADER */
58
+ .header {
59
+ margin-bottom: 10px;
60
+ border-bottom: 1px solid #00d4ff;
61
+ padding-bottom: 6px;
21
62
  }
22
63
 
23
- button:hover {
24
- background: #3a3a3a;
64
+ .header h3 {
65
+ font-size: 16px;
66
+ color: #00d4ff;
25
67
  }
26
68
 
27
- input {
28
- background: #252526;
29
- color: white;
30
- border: 1px solid #444;
31
- padding: 5px;
69
+ .header h1 {
70
+ font-size: 2.5em;
71
+ background: linear-gradient(135deg, #00d4ff, #0099cc);
72
+ -webkit-background-clip: text;
73
+ -webkit-text-fill-color: transparent;
74
+ background-clip: text;
75
+ margin-bottom: 8px;
76
+ font-weight: 700;
32
77
  }
33
78
 
34
- #screenCanvas {
35
- border: 2px solid #4fc3f7;
36
- margin-top: 10px;
79
+ .header .subtitle {
80
+ color: #888;
81
+ font-size: 0.95em;
82
+ font-weight: 300;
83
+ letter-spacing: 0.5px;
37
84
  }
38
85
 
39
- #templatePreview {
40
- border: 1px solid #4fc3f7;
41
- margin-top: 10px;
86
+ /* SECTIONS */
87
+ .section-title {
88
+ font-size: 1.2em;
89
+ color: #00d4ff;
90
+ margin-bottom: 18px;
91
+ margin-top: 0;
92
+ font-weight: 600;
93
+ display: flex;
94
+ align-items: center;
95
+ gap: 8px;
42
96
  }
43
97
 
44
- #matchResult {
45
- margin-top: 10px;
98
+ /* CONTROLS SECTION */
99
+ .controls-section {
100
+ background: rgba(255, 255, 255, 0.03);
101
+ border: 1px solid rgba(0, 212, 255, 0.2);
102
+ border-radius: 12px;
46
103
  padding: 10px;
47
- border: 1px solid #333;
48
- background: #252526;
104
+ margin-bottom: 15px;
105
+ backdrop-filter: blur(10px);
49
106
  }
50
107
 
51
108
  .toolbar {
52
- margin-bottom: 15px;
53
- }
109
+ display: flex;
110
+ gap: 6px;
111
+ margin-bottom: 8px;
112
+ align-items: center;
113
+ }
114
+
115
+ .btn {
116
+ padding: 4px 8px;
117
+ border: none;
118
+ border-radius: 8px;
119
+ cursor: pointer;
120
+ font-size: 12px;
121
+ font-weight: 500;
122
+ transition: all 0.3s ease;
123
+ display: flex;
124
+ align-items: center;
125
+ gap: 3px;
126
+ white-space: nowrap;
127
+ }
128
+
129
+ .btn-icon {
130
+ font-size: 1.1em;
131
+ }
132
+
133
+ .btn-primary {
134
+ background: linear-gradient(135deg, #00d4ff, #0099cc);
135
+ color: #000;
136
+ font-weight: 600;
137
+ }
138
+
139
+ .btn-primary:hover {
140
+ transform: translateY(-2px);
141
+ box-shadow: 0 8px 20px rgba(0, 212, 255, 0.4);
142
+ }
143
+
144
+ .btn-primary:active {
145
+ transform: translateY(0);
146
+ }
147
+
148
+ .btn-secondary {
149
+ background: rgba(100, 150, 180, 0.2);
150
+ color: #e0e0e0;
151
+ border: 1px solid rgba(0, 212, 255, 0.3);
152
+ }
153
+
154
+ .btn-secondary:hover {
155
+ background: rgba(100, 150, 180, 0.3);
156
+ border-color: rgba(0, 212, 255, 0.6);
157
+ transform: translateY(-2px);
158
+ }
159
+
160
+ .btn-accent {
161
+ background: rgba(76, 175, 80, 0.2);
162
+ color: #4caf50;
163
+ border: 1px solid rgba(76, 175, 80, 0.5);
164
+ }
165
+
166
+ .btn-accent:hover {
167
+ background: rgba(76, 175, 80, 0.3);
168
+ border-color: #4caf50;
169
+ transform: translateY(-2px);
170
+ }
171
+
172
+ /* CONTROLS GRID */
173
+ .controls-grid {
174
+ display: grid;
175
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
176
+ gap: 20px;
177
+ }
178
+
179
+ .control-group {
180
+ display: flex;
181
+ flex-direction: column;
182
+ gap: 8px;
183
+ }
184
+
185
+ .control-group label {
186
+ font-size: 0.8em;
187
+ color: #b0b0b0;
188
+ font-weight: 500;
189
+ }
190
+
191
+ .input-wrapper {
192
+ display: flex;
193
+ align-items: center;
194
+ gap: 10px;
195
+ }
196
+
197
+ input[type="number"] {
198
+ background: rgba(37, 37, 38, 0.8);
199
+ color: #00d4ff;
200
+ border: 1px solid rgba(0, 212, 255, 0.3);
201
+ padding: 10px 12px;
202
+ border-radius: 6px;
203
+ font-size: 0.8em;
204
+ width: 60px;
205
+ transition: all 0.3s ease;
206
+ }
207
+
208
+ input[type="number"]:focus {
209
+ outline: none;
210
+ border-color: #00d4ff;
211
+ box-shadow: 0 0 12px rgba(0, 212, 255, 0.2);
212
+ background: rgba(37, 37, 38, 1);
213
+ }
214
+
215
+ .input-hint {
216
+ color: #666;
217
+ font-size: 0.85em;
218
+ }
219
+
220
+ /* CANVAS SECTION */
221
+ .canvas-section {
222
+ background: rgba(255, 255, 255, 0.02);
223
+ border: 1px solid rgba(0, 212, 255, 0.2);
224
+ border-radius: 12px;
225
+ padding: 10px;
226
+ margin-bottom: 10px;
227
+ }
228
+
229
+ .canvas {
230
+ border: 2px solid #00d4ff;
231
+ border-radius: 8px;
232
+ background: #0a0a0a;
233
+ display: block;
234
+ margin-top: 15px;
235
+ box-shadow: 0 0 20px rgba(0, 212, 255, 0.1);
236
+ }
237
+
238
+ /* TEMPLATE SECTION */
239
+ .template-section {
240
+ background: rgba(255, 255, 255, 0.02);
241
+ border: 1px solid rgba(0, 212, 255, 0.2);
242
+ border-radius: 12px;
243
+ padding: 10px;
244
+ margin-bottom: 10px;
245
+ }
246
+
247
+ .template-grid {
248
+ display: grid;
249
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
250
+ gap: 20px;
251
+ }
252
+
253
+ .template-info {
254
+ display: flex;
255
+ flex-direction: column;
256
+ gap: 10px;
257
+ }
258
+
259
+ .template-info p {
260
+ font-size: 0.95em;
261
+ color: #b0b0b0;
262
+ }
263
+
264
+ .template-status {
265
+ display: inline-block;
266
+ padding: 8px 14px;
267
+ background: rgba(76, 175, 80, 0.15);
268
+ border: 1px solid rgba(76, 175, 80, 0.3);
269
+ border-radius: 6px;
270
+ color: #4caf50;
271
+ font-weight: 500;
272
+ width: fit-content;
273
+ }
274
+
275
+ .template-preview {
276
+ border: 2px solid #00d4ff;
277
+ border-radius: 8px;
278
+ max-width: 100%;
279
+ height: auto;
280
+ max-height: 150px;
281
+ object-fit: contain;
282
+ background: #0a0a0a;
283
+ box-shadow: 0 0 20px rgba(0, 212, 255, 0.1);
284
+ display: none;
285
+ }
286
+
287
+ .template-preview[src]:not([src=""]) {
288
+ display: block;
289
+ }
290
+
291
+ /* RESULTS SECTION */
292
+ .results-section {
293
+ background: rgba(255, 255, 255, 0.02);
294
+ border: 1px solid rgba(0, 212, 255, 0.2);
295
+ border-radius: 12px;
296
+ padding: 10px;
297
+ }
298
+
299
+ /* RESULTS GRID */
300
+ .results-grid {
301
+ display: grid;
302
+ grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
303
+ gap: 12px;
304
+ }
305
+
306
+ .result-card {
307
+ background: rgba(0, 212, 255, 0.08);
308
+ border: 1px solid rgba(0, 212, 255, 0.3);
309
+ border-radius: 8px;
310
+ padding: 4px;
311
+ min-height: 50px;
312
+ display: flex;
313
+ flex-direction: column;
314
+ align-items: center;
315
+ gap: 6px;
316
+ transition: all 0.3s ease;
317
+ text-align: center;
318
+ }
319
+
320
+ .result-card:hover {
321
+ background: rgba(0, 212, 255, 0.12);
322
+ border-color: rgba(0, 212, 255, 0.5);
323
+ transform: translateY(-2px);
324
+ box-shadow: 0 4px 12px rgba(0, 212, 255, 0.15);
325
+ }
326
+
327
+
328
+ .result-label {
329
+ color: #888;
330
+ font-size: 0.8em;
331
+ font-weight: 500;
332
+ text-transform: uppercase;
333
+ letter-spacing: 0.5px;
334
+ }
335
+
336
+ .result-value {
337
+ color: #00d4ff;
338
+ font-weight: 700;
339
+ font-size: 0.8em;
340
+ font-family: 'Courier New', monospace;
341
+ }
342
+
343
+ #matchResult {
344
+ margin-top: 15px;
345
+ padding: 15px;
346
+ border-radius: 8px;
347
+ background: rgba(37, 37, 38, 0.6);
348
+ border: 1px solid rgba(100, 150, 180, 0.2);
349
+ min-height: 60px;
350
+ display: flex;
351
+ align-items: center;
352
+ justify-content: center;
353
+ color: #888;
354
+ font-size: 0.8em;
355
+ }
356
+
357
+ #matchResult:not(:empty) {
358
+ background: rgba(76, 175, 80, 0.1);
359
+ border-color: rgba(76, 175, 80, 0.3);
360
+ color: #e0e0e0;
361
+ }
362
+
363
+ /* RESPONSIVE */
364
+ @media (max-width: 768px) {
365
+ .container {
366
+ padding: 12px;
367
+ }
368
+
369
+ .header h1 {
370
+ font-size: 1.8em;
371
+ }
372
+
373
+ .toolbar {
374
+ flex-direction: column;
375
+ gap: 10px;
376
+ }
377
+
378
+ .btn {
379
+ width: 100%;
380
+ justify-content: center;
381
+ }
382
+
383
+ .controls-grid {
384
+ grid-template-columns: 1fr;
385
+ }
386
+
387
+ .template-grid {
388
+ grid-template-columns: 1fr;
389
+ }
390
+ }
391
+
392
+ /* SCROLLBAR STYLING */
393
+ ::-webkit-scrollbar {
394
+ width: 8px;
395
+ height: 8px;
396
+ }
397
+
398
+ ::-webkit-scrollbar-track {
399
+ background: rgba(37, 37, 38, 0.5);
400
+ border-radius: 10px;
401
+ }
402
+
403
+ ::-webkit-scrollbar-thumb {
404
+ background: rgba(0, 212, 255, 0.4);
405
+ border-radius: 10px;
406
+ }
407
+
408
+ ::-webkit-scrollbar-thumb:hover {
409
+ background: rgba(0, 212, 255, 0.6);
410
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aspiresys/visor",
3
- "version": "1.2.5",
3
+ "version": "1.2.7",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "scripts": {