noobs 0.0.65 → 0.0.84

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/noobs.node CHANGED
Binary file
package/index.d.ts CHANGED
@@ -189,6 +189,7 @@ interface Noobs {
189
189
  InitPreview(hwnd: Buffer): void;
190
190
  ShowPreview(x: number, y: number, width: number, height: number): void;
191
191
  HidePreview(): void;
192
+ GetPreviewScaleFactor(): number;
192
193
  }
193
194
 
194
195
  declare const noobs: Noobs;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "noobs",
3
- "version": "0.0.65",
3
+ "version": "0.0.84",
4
4
  "description": "A native Node.js addon with libobs bindings for Warcraft Recorder.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
package/src/main.cpp CHANGED
@@ -195,6 +195,16 @@ Napi::Value ObsHidePreview(const Napi::CallbackInfo& info) {
195
195
  return info.Env().Undefined();
196
196
  }
197
197
 
198
+ Napi::Value ObsGetPreviewScaleFactor(const Napi::CallbackInfo& info) {
199
+ if (!obs) {
200
+ blog(LOG_ERROR, "ObsGetPreviewScaleFactor called but obs is not initialized");
201
+ throw std::runtime_error("Obs not initialized");
202
+ }
203
+
204
+ float scaleFactor = obs->getPreviewScaleFactor();
205
+ return Napi::Number::New(info.Env(), scaleFactor);
206
+ }
207
+
198
208
  Napi::Value ObsCreateSource(const Napi::CallbackInfo& info) {
199
209
  if (!obs) {
200
210
  blog(LOG_ERROR, "ObsCreateSource called but obs is not initialized");
@@ -443,6 +453,7 @@ Napi::Object Init(Napi::Env env, Napi::Object exports) {
443
453
  exports.Set("InitPreview", Napi::Function::New(env, ObsInitPreview));
444
454
  exports.Set("ShowPreview", Napi::Function::New(env, ObsShowPreview));
445
455
  exports.Set("HidePreview", Napi::Function::New(env, ObsHidePreview));
456
+ exports.Set("GetPreviewScaleFactor", Napi::Function::New(env, ObsGetPreviewScaleFactor));
446
457
 
447
458
  return exports;
448
459
  }
@@ -124,6 +124,11 @@ void ObsInterface::reset_video() {
124
124
 
125
125
  int success = obs_reset_video(&ovi);
126
126
 
127
+ obs_enter_graphics();
128
+ int dt = gs_get_device_type();
129
+ blog(LOG_INFO, "Device type = %d", dt); // should be 1 for D3D11
130
+ obs_leave_graphics();
131
+
127
132
  if (success != OBS_VIDEO_SUCCESS) {
128
133
  blog(LOG_ERROR, "Failed to reset video!");
129
134
  throw std::runtime_error("Failed to reset video!");
@@ -163,7 +168,14 @@ void ObsInterface::init_obs(const std::string& pluginPath, const std::string& da
163
168
  dp += '/';
164
169
  }
165
170
 
166
- obs_add_data_path(dp.c_str()); // This is deprecated in libobs but it works for now.
171
+ // We need this before resetting video and audio to ensure the effects
172
+ // are available. The function is deprecated in libobs but it works for
173
+ // now.
174
+ obs_add_data_path(dp.c_str());
175
+
176
+ // This must come before loading modules to initialize D3D11.
177
+ reset_video();
178
+ reset_audio();
167
179
 
168
180
  std::vector<std::string> modules = {
169
181
  "obs-x264.dll",
@@ -185,9 +197,6 @@ void ObsInterface::init_obs(const std::string& pluginPath, const std::string& da
185
197
  list_input_types();
186
198
  list_output_types();
187
199
 
188
- reset_video();
189
- reset_audio();
190
-
191
200
  blog(LOG_INFO, "Exit init_obs");
192
201
  }
193
202
 
@@ -285,9 +294,9 @@ void ObsInterface::create_video_encoders() {
285
294
 
286
295
  blog(LOG_INFO, "Set file video encoder settings");
287
296
  obs_data_t* venc_settings = obs_data_create();
288
- obs_data_set_string(venc_settings, "preset", "speed"); // Faster preset
297
+ // obs_data_set_string(venc_settings, "preset", "speed"); // Faster preset
289
298
  obs_data_set_string(venc_settings, "rate_control", "CRF");
290
- obs_data_set_int(venc_settings, "crf", 30);
299
+ obs_data_set_int(venc_settings, "crf", 22);
291
300
  obs_data_set_string(venc_settings, "profile", "main");
292
301
  obs_data_set_int(venc_settings, "keyint_sec", 1); // Set keyframe interval to 1 second
293
302
 
@@ -513,6 +522,12 @@ bool draw_box(obs_scene_t *scene, obs_sceneitem_t *item, void *p) {
513
522
  float width = obs_source_get_width(src) * scale.x;
514
523
  float height = obs_source_get_height(src) * scale.y;
515
524
 
525
+ if (width <= 0 || height <= 0) {
526
+ // Don't want to call gs_draw_sprite with zero width or height.
527
+ // It is obviously nonsense and leads to log spam. Just return early.
528
+ return true;
529
+ }
530
+
516
531
  // Draw rectangle around the source using the position and size
517
532
  gs_effect_t *solid = obs_get_base_effect(OBS_EFFECT_SOLID);
518
533
  gs_eparam_t *color = gs_effect_get_param_by_name(solid, "color");
@@ -530,25 +545,25 @@ bool draw_box(obs_scene_t *scene, obs_sceneitem_t *item, void *p) {
530
545
  // Top border
531
546
  gs_matrix_push();
532
547
  gs_matrix_translate3f(pos.x, pos.y, 0.0f);
533
- gs_draw_sprite(nullptr, 0, width, 2.0f);
548
+ gs_draw_sprite(nullptr, 0, width, 4.0f);
534
549
  gs_matrix_pop();
535
550
 
536
551
  // Bottom border
537
552
  gs_matrix_push();
538
- gs_matrix_translate3f(pos.x, pos.y + height - 2.0f, 0.0f);
539
- gs_draw_sprite(nullptr, 0, width, 2.0f);
553
+ gs_matrix_translate3f(pos.x, pos.y + height - 4.0f, 0.0f);
554
+ gs_draw_sprite(nullptr, 0, width, 4.0f);
540
555
  gs_matrix_pop();
541
556
 
542
557
  // Left border
543
558
  gs_matrix_push();
544
559
  gs_matrix_translate3f(pos.x, pos.y, 0.0f);
545
- gs_draw_sprite(nullptr, 0, 2.0f, height);
560
+ gs_draw_sprite(nullptr, 0, 4.0f, height);
546
561
  gs_matrix_pop();
547
562
 
548
563
  // Right border
549
564
  gs_matrix_push();
550
- gs_matrix_translate3f(pos.x + width - 2.0f, pos.y, 0.0f);
551
- gs_draw_sprite(nullptr, 0, 2.0f, height);
565
+ gs_matrix_translate3f(pos.x + width - 4.0f, pos.y, 0.0f);
566
+ gs_draw_sprite(nullptr, 0, 4.0f, height);
552
567
  gs_matrix_pop();
553
568
 
554
569
  gs_matrix_pop();
@@ -560,22 +575,46 @@ bool draw_box(obs_scene_t *scene, obs_sceneitem_t *item, void *p) {
560
575
  }
561
576
 
562
577
  void draw_callback(void* data, uint32_t cx, uint32_t cy) {
563
- // Initially, draw the OBS scene texture
564
- obs_render_main_texture();
578
+ obs_video_info ovi;
579
+ obs_get_video_info(&ovi);
565
580
 
566
- // This is some AI code that would draw a rectangle (and works).
567
- // Set projection and viewport
568
- gs_ortho(0.0f, float(cx), 0.0f, float(cy), -100.0f, 100.0f);
569
- gs_set_viewport(0, 0, cx, cy);
581
+ float scaleX = float(cx) / float(ovi.base_width);
582
+ float scaleY = float(cy) / float(ovi.base_height);
583
+
584
+ float previewScale;
585
+
586
+ // Pick the limiting scale factor.
587
+ if (scaleX < scaleY) {
588
+ previewScale = scaleX;
589
+ } else {
590
+ previewScale = scaleY;
591
+ }
592
+
593
+ int previewCX = int(previewScale * ovi.base_width);
594
+ int previewCY = int(previewScale * ovi.base_height);
595
+ int previewX = (cx - previewCX) / 2;
596
+ int previewY = (cy - previewCY) / 2;
597
+
598
+ gs_viewport_push();
599
+ gs_projection_push();
600
+
601
+ gs_ortho(0.0f, float(ovi.base_width), 0.0f, float(ovi.base_height), -100.0f, 100.0f);
602
+ gs_set_viewport(previewX, previewY, previewCX, previewCY);
603
+
604
+ // Renders the scene now the graphics context is setup.
605
+ obs_render_main_texture();
570
606
 
571
- // This was me trying to understand what OSN does.
607
+ // Draw boxes around sources.
572
608
  obs_scene_t* scene = obs_get_scene_by_name("WCR Scene");
573
609
  obs_scene_enum_items(scene, draw_box, NULL);
574
610
  obs_scene_release(scene);
611
+
612
+ gs_projection_pop();
613
+ gs_viewport_pop();
575
614
  }
576
615
 
577
616
  void ObsInterface::initPreview(HWND parent) {
578
- blog(LOG_INFO, "ObsInterface::showPreview");
617
+ blog(LOG_INFO, "ObsInterface::initPreview");
579
618
 
580
619
  if (!preview_hwnd) {
581
620
  blog(LOG_INFO, "Creating preview child window");
@@ -632,13 +671,15 @@ void ObsInterface::showPreview(int x, int y, int width, int height) {
632
671
  return;
633
672
  }
634
673
 
674
+ blog(LOG_INFO, "Showing preview child window at (%d, %d) with size (%d x %d)", x, y, width, height);
675
+
635
676
  // Resize and move the existing child window.
636
677
  bool success = SetWindowPos(
637
678
  preview_hwnd, // Handle to the child window
638
679
  NULL, // No Z-order change
639
680
  x, y, // New position (x, y)
640
681
  width, height, // New size (width, height)
641
- SWP_NOZORDER | SWP_NOACTIVATE // Don't change position, Z-order, or activation
682
+ SWP_NOACTIVATE // Flags
642
683
  );
643
684
 
644
685
  if (!success) {
@@ -646,6 +687,11 @@ void ObsInterface::showPreview(int x, int y, int width, int height) {
646
687
  return;
647
688
  }
648
689
 
690
+ uint32_t w, h;
691
+ obs_display_size(display, &w, &h); // Get the display size to match the video context.
692
+ blog(LOG_INFO, "Current Display size set to (%d x %d)", w, h);
693
+
694
+ obs_display_resize(display, width, height);
649
695
  ShowWindow(preview_hwnd, SW_SHOW);
650
696
  obs_display_set_enabled(display, true);
651
697
  }
@@ -661,6 +707,33 @@ void ObsInterface::hidePreview() {
661
707
  obs_display_set_enabled(display, false);
662
708
  }
663
709
 
710
+ float ObsInterface::getPreviewScaleFactor() {
711
+ if (!display) {
712
+ blog(LOG_WARNING, "Display not initialized");
713
+ return 1.0f; // Default scale
714
+ }
715
+
716
+ obs_video_info ovi;
717
+ obs_get_video_info(&ovi);
718
+
719
+ uint32_t width, height;
720
+ obs_display_size(display, &width, &height);
721
+
722
+ float scaleX = float(width) / float(ovi.base_width);
723
+ float scaleY = float(height) / float(ovi.base_height);
724
+
725
+ float previewScale;
726
+
727
+ // Pick the limiting scale factor.
728
+ if (scaleX < scaleY) {
729
+ previewScale = scaleX;
730
+ } else {
731
+ previewScale = scaleY;
732
+ }
733
+
734
+ return previewScale;
735
+ }
736
+
664
737
  ObsInterface::ObsInterface(
665
738
  const std::string& pluginPath,
666
739
  const std::string& logPath,
@@ -915,8 +988,6 @@ void ObsInterface::removeSourceFromScene(std::string name) {
915
988
 
916
989
  void ObsInterface::getSourcePos(std::string name, vec2* pos, vec2* size, vec2* scale)
917
990
  {
918
- blog(LOG_INFO, "ObsInterface::getSourcePos called");
919
-
920
991
  obs_source_t *src = obs_get_source_by_name(name.c_str());
921
992
  obs_sceneitem_t *item = obs_scene_find_source(scene, name.c_str());
922
993
 
@@ -936,12 +1007,9 @@ void ObsInterface::getSourcePos(std::string name, vec2* pos, vec2* size, vec2* s
936
1007
  // Pre-scaled sizes.
937
1008
  size->x = obs_source_get_width(src);
938
1009
  size->y = obs_source_get_height(src);
939
-
940
- blog(LOG_INFO, "ObsInterface::getSourcePos exited");
941
1010
  }
942
1011
 
943
1012
  void ObsInterface::setSourcePos(std::string name, vec2* pos, vec2* scale) {
944
- blog(LOG_INFO, "ObsInterface::moveSource called");
945
1013
  obs_sceneitem_t *item = obs_scene_find_source(scene, name.c_str());
946
1014
 
947
1015
  if (!item) {
@@ -40,6 +40,7 @@ class ObsInterface {
40
40
  void initPreview(HWND parent); // Must call this before showPreview to setup resources.
41
41
  void showPreview(int x, int y, int width, int height); // Also used for moving and resizing.
42
42
  void hidePreview(); // Hide the preview display.
43
+ float getPreviewScaleFactor(); // Get the current scale factor of the preview.
43
44
 
44
45
  std::vector<std::string> get_available_video_encoders();
45
46