diff --git a/scripts/startup/bl_ui/space_view3d.py b/scripts/startup/bl_ui/space_view3d.py
index b151c72a5a6..2a88807403f 100644
--- a/scripts/startup/bl_ui/space_view3d.py
+++ b/scripts/startup/bl_ui/space_view3d.py
@@ -659,8 +659,12 @@ class VIEW3D_HT_header(Header):
         # Orientation
         if object_mode in {'OBJECT', 'EDIT', 'EDIT_GPENCIL'} or has_pose_mode:
             orient_slot = scene.transform_orientation_slots[0]
+            view = context.space_data
+
             row = layout.row(align=True)
+            row.prop(view, "ucs", text="UCS")
 
+            row = layout.row(align=True)
             sub = row.row()
             sub.ui_units_x = 4
             sub.prop_with_popover(
diff --git a/source/blender/draw/engines/overlay/overlay_grid.cc b/source/blender/draw/engines/overlay/overlay_grid.cc
index 4c5581a575f..93723765876 100644
--- a/source/blender/draw/engines/overlay/overlay_grid.cc
+++ b/source/blender/draw/engines/overlay/overlay_grid.cc
@@ -104,10 +104,13 @@ void OVERLAY_grid_init(OVERLAY_Data *vedata)
 
     float viewinv[4][4], wininv[4][4];
     float viewmat[4][4], winmat[4][4];
+    float ucsmat[4][4], ucsinv[4][4];
     DRW_view_winmat_get(nullptr, winmat, false);
     DRW_view_winmat_get(nullptr, wininv, true);
     DRW_view_viewmat_get(nullptr, viewmat, false);
     DRW_view_viewmat_get(nullptr, viewinv, true);
+    DRW_view_ucsmat_get(nullptr, ucsmat, false);
+    DRW_view_ucsmat_get(nullptr, ucsinv, true);
 
     /* If perspective view or non-axis aligned view. */
     if (winmat[3][3] == 0.0f || rv3d->view == RV3D_VIEW_USER) {
@@ -142,8 +145,8 @@ void OVERLAY_grid_init(OVERLAY_Data *vedata)
       zpos_flag = SHOW_AXIS_Z;
 
       float zvec[3], campos[3];
-      negate_v3_v3(zvec, viewinv[2]);
-      copy_v3_v3(campos, viewinv[3]);
+      negate_v3_v3(zvec, ucsinv[2]);
+      copy_v3_v3(campos, ucsinv[3]);
 
       /* z axis : chose the most facing plane */
       if (fabsf(zvec[0]) < fabsf(zvec[1])) {
@@ -205,7 +208,7 @@ void OVERLAY_grid_init(OVERLAY_Data *vedata)
        * component, which may not be correct if the user is "shrunk" or "enlarged" by zooming in or
        * out. Therefore, we need to compensate the values here. */
       /* Assumption is uniform scaling (all column vectors are of same length). */
-      float viewinvscale = len_v3(viewinv[0]);
+      float viewinvscale = len_v3(ucsinv[0]);
       grid->distance *= viewinvscale;
     }
   }
diff --git a/source/blender/draw/engines/overlay/shaders/overlay_grid_vert.glsl b/source/blender/draw/engines/overlay/shaders/overlay_grid_vert.glsl
index 9c0578edc63..8b42721f967 100644
--- a/source/blender/draw/engines/overlay/shaders/overlay_grid_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/overlay_grid_vert.glsl
@@ -44,5 +44,5 @@ void main()
     local_pos.z = clamp(local_pos.z, -1.0, 0.0);
   }
 
-  gl_Position = drw_view.winmat * (drw_view.viewmat * vec4(real_pos, 1.0));
+  gl_Position = drw_view.winmat * (drw_view.ucsmat * vec4(real_pos, 1.0));
 }
diff --git a/source/blender/draw/intern/DRW_render.hh b/source/blender/draw/intern/DRW_render.hh
index 80baf02abf5..dadf7c99317 100644
--- a/source/blender/draw/intern/DRW_render.hh
+++ b/source/blender/draw/intern/DRW_render.hh
@@ -693,6 +693,16 @@ bool DRW_pass_is_empty(DRWPass *pass);
 
 /* Views. */
 
+/**
+ * Create a view with culling.
+ */
+DRWView *DRW_view_create(const float viewmat[4][4],
+                         const float winmat[4][4],
+                         const float (*culling_viewmat)[4],
+                         const float (*culling_winmat)[4],
+                         DRWCallVisibilityFn *visibility_fn);
+
+
 /**
  * Create a view with culling.
  */
@@ -716,6 +726,10 @@ void DRW_view_update(DRWView *view,
                      const float winmat[4][4],
                      const float (*culling_viewmat)[4],
                      const float (*culling_winmat)[4]);
+/**
+* Update ucs matrix
+*/
+void DRW_view_ucs_update(DRWView *view, const float ucsmat[4][4]);
 /**
  * Update matrices of a view created with #DRW_view_create_sub.
  */
@@ -750,6 +764,7 @@ void DRW_view_clip_planes_set(DRWView *view, float (*planes)[4], int plane_len);
 
 void DRW_view_winmat_get(const DRWView *view, float mat[4][4], bool inverse);
 void DRW_view_viewmat_get(const DRWView *view, float mat[4][4], bool inverse);
+void DRW_view_ucsmat_get(const DRWView *view, float mat[4][4], bool inverse);
 void DRW_view_persmat_get(const DRWView *view, float mat[4][4], bool inverse);
 
 /**
diff --git a/source/blender/draw/intern/draw_manager_c.cc b/source/blender/draw/intern/draw_manager_c.cc
index 4fc72359b16..5a3236fea5a 100644
--- a/source/blender/draw/intern/draw_manager_c.cc
+++ b/source/blender/draw/intern/draw_manager_c.cc
@@ -581,6 +581,7 @@ static void drw_manager_init(DRWManager *dst, GPUViewport *viewport, const int s
   if (rv3d != nullptr) {
     dst->pixsize = rv3d->pixsize;
     dst->view_default = DRW_view_create(rv3d->viewmat, rv3d->winmat, nullptr, nullptr, nullptr);
+    DRW_view_ucs_update(dst->view_default, rv3d->ucsmat);
 
     if (dst->draw_ctx.sh_cfg == GPU_SHADER_CFG_CLIPPED) {
       int plane_len = (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXCLIP) ? 4 : 6;
diff --git a/source/blender/draw/intern/draw_manager_data.cc b/source/blender/draw/intern/draw_manager_data.cc
index 825f8fc390b..a53b3a2fe4e 100644
--- a/source/blender/draw/intern/draw_manager_data.cc
+++ b/source/blender/draw/intern/draw_manager_data.cc
@@ -2294,6 +2294,11 @@ void DRW_view_update(DRWView *view,
 #endif
 }
 
+
+void DRW_view_ucs_update(DRWView *view, const float ucsmat[4][4]) {
+  copy_m4_m4(view->storage.ucsmat.ptr(), ucsmat);
+}
+
 const DRWView *DRW_view_default_get()
 {
   return DST.view_default;
@@ -2368,6 +2373,20 @@ void DRW_view_viewmat_get(const DRWView *view, float mat[4][4], bool inverse)
   copy_m4_m4(mat, (inverse) ? storage->viewinv.ptr() : storage->viewmat.ptr());
 }
 
+void DRW_view_ucsmat_get(const DRWView *view, float mat[4][4], bool inverse)
+{
+  view = (view) ? view : DST.view_default;
+  const ViewMatrices *storage = &view->storage;
+  copy_m4_m4(mat, storage->ucsmat.ptr());
+  if (inverse) {
+    float tmp[4][4];
+    invert_m4_m4(tmp, mat);
+    copy_m4_m4(mat, tmp);
+  }
+}
+
+
+
 void DRW_view_winmat_get(const DRWView *view, float mat[4][4], bool inverse)
 {
   view = (view) ? view : DST.view_default;
diff --git a/source/blender/draw/intern/draw_shader_shared.h b/source/blender/draw/intern/draw_shader_shared.h
index 754a38a5f16..cfa3511c85c 100644
--- a/source/blender/draw/intern/draw_shader_shared.h
+++ b/source/blender/draw/intern/draw_shader_shared.h
@@ -125,6 +125,7 @@ struct ViewMatrices {
   float4x4 viewinv;
   float4x4 winmat;
   float4x4 wininv;
+  float4x4 ucsmat;
 };
 BLI_STATIC_ASSERT_ALIGN(ViewMatrices, 16)
 
diff --git a/source/blender/editors/include/ED_transform.hh b/source/blender/editors/include/ED_transform.hh
index 24869d9f413..ae3b2b23304 100644
--- a/source/blender/editors/include/ED_transform.hh
+++ b/source/blender/editors/include/ED_transform.hh
@@ -82,7 +82,7 @@ bool calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], floa
 void BIF_clearTransformOrientation(bContext *C);
 void BIF_removeTransformOrientation(bContext *C, TransformOrientation *target);
 void BIF_removeTransformOrientationIndex(bContext *C, int index);
-bool BIF_createTransformOrientation(bContext *C,
+TransformOrientation* BIF_createTransformOrientation(bContext *C,
                                     ReportList *reports,
                                     const char *name,
                                     bool use_view,
diff --git a/source/blender/editors/include/ED_view3d.hh b/source/blender/editors/include/ED_view3d.hh
index d3cd26de431..49065d37ab0 100644
--- a/source/blender/editors/include/ED_view3d.hh
+++ b/source/blender/editors/include/ED_view3d.hh
@@ -57,6 +57,8 @@ struct wmOperator;
 struct wmWindow;
 struct wmWindowManager;
 
+struct TransformOrientation;
+
 /* for derivedmesh drawing callbacks, for view3d_select, .... */
 struct ViewContext {
   bContext *C;
@@ -1048,6 +1050,15 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph,
                               const rcti *rect,
                               bool offscreen);
 bool ED_view3d_quat_from_axis_view(char view, char view_axis_roll, float r_quat[4]);
+
+bool ED_view3d_quat_from_axis_view_transform(
+    Scene *scene, View3D *v3d, const char view, const char view_axis_roll, float r_quat[4]);
+
+bool ED_view3d_quat_from_axis_view_ucs(TransformOrientation *ts,
+                                       char viewnum,
+                                       char view_axis_roll,
+                                       float quat[4]);
+
 bool ED_view3d_quat_to_axis_view(const float viewquat[4],
                                  float epsilon,
                                  char *r_view,
@@ -1067,6 +1078,9 @@ char ED_view3d_lock_view_from_index(int index);
 char ED_view3d_axis_view_opposite(char view);
 bool ED_view3d_lock(RegionView3D *rv3d);
 
+bool ED_view3d_lock_ucs(TransformOrientation *ts, struct RegionView3D *rv3d);
+
+
 void ED_view3d_datamask(const Scene *scene,
                         ViewLayer *view_layer,
                         const View3D *v3d,
diff --git a/source/blender/editors/screen/screen_ops.cc b/source/blender/editors/screen/screen_ops.cc
index ed735d4244e..8ee42ee829f 100644
--- a/source/blender/editors/screen/screen_ops.cc
+++ b/source/blender/editors/screen/screen_ops.cc
@@ -4025,9 +4025,10 @@ static void view3d_localview_update_rv3d(RegionView3D *rv3d)
 }
 
 static void region_quadview_init_rv3d(
-    ScrArea *area, ARegion *region, const char viewlock, const char view, const char persp)
+    ScrArea *area, Scene *scene, ARegion *region, const char viewlock, const char view, const char persp)
 {
   RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
+  View3D *v3d = static_cast<View3D *>(area->spacedata.first);
 
   if (persp == RV3D_CAMOB) {
     ED_view3d_lastview_store(rv3d);
@@ -4039,7 +4040,27 @@ static void region_quadview_init_rv3d(
   rv3d->view_axis_roll = RV3D_VIEW_AXIS_ROLL_0;
   rv3d->persp = persp;
 
-  ED_view3d_lock(rv3d);
+  if (v3d->ucs) {
+    TransformOrientation *custom_orientation = nullptr;
+    if (scene->orientation_slots->type >= V3D_ORIENT_CUSTOM &&
+         scene->orientation_slots->index_custom != -1)
+    {
+      custom_orientation = BKE_scene_transform_orientation_find(
+          scene, scene->orientation_slots->index_custom);
+    }
+
+    if (custom_orientation) {
+      ED_view3d_lock_ucs(custom_orientation, rv3d);
+    }
+    else {
+      // Invalid ucs
+      ED_view3d_lock(rv3d);
+    }
+  }
+  else {
+    // Global
+    ED_view3d_lock(rv3d);
+  }
   view3d_localview_update_rv3d(rv3d);
   if ((viewlock & RV3D_BOXCLIP) && (persp == RV3D_ORTHO)) {
     ED_view3d_quadview_update(area, region, true);
@@ -4108,6 +4129,7 @@ static int region_quadview_exec(bContext *C, wmOperator *op)
   else {
     /* Enter quad-view */
     ScrArea *area = CTX_wm_area(C);
+    Scene *scene = CTX_data_scene(C);
 
     region->alignment = RGN_ALIGN_QSPLIT;
 
@@ -4132,14 +4154,20 @@ static int region_quadview_exec(bContext *C, wmOperator *op)
                                 (rv3d->viewlock_quad & ~RV3D_VIEWLOCK_INIT) :
                                 RV3D_LOCK_ROTATION;
 
-      region_quadview_init_rv3d(
-          area, region, viewlock, ED_view3d_lock_view_from_index(index_qsplit++), RV3D_ORTHO);
       region_quadview_init_rv3d(area,
+                                scene,
+                                (region = region->next),
+                                viewlock,
+                                ED_view3d_lock_view_from_index(index_qsplit++),
+                                RV3D_ORTHO);
+      region_quadview_init_rv3d(area,
+                                scene,
                                 (region = region->next),
                                 viewlock,
                                 ED_view3d_lock_view_from_index(index_qsplit++),
                                 RV3D_ORTHO);
       region_quadview_init_rv3d(area,
+                                scene, 
                                 (region = region->next),
                                 viewlock,
                                 ED_view3d_lock_view_from_index(index_qsplit++),
diff --git a/source/blender/editors/space_view3d/view3d_draw.cc b/source/blender/editors/space_view3d/view3d_draw.cc
index 738e2830b24..a0c8b791dc6 100644
--- a/source/blender/editors/space_view3d/view3d_draw.cc
+++ b/source/blender/editors/space_view3d/view3d_draw.cc
@@ -134,6 +134,40 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph,
     /* NOTE: calls BKE_object_where_is_calc for camera... */
     view3d_viewmatrix_set(depsgraph, scene, v3d, rv3d, rect ? rect_scale : nullptr);
   }
+
+  if (v3d->ucs > 0) {
+    TransformOrientation *custom_orientation = nullptr;
+    if (scene->orientation_slots->type >= V3D_ORIENT_CUSTOM &&
+         +scene->orientation_slots->index_custom != -1) 
+    {
+      custom_orientation = BKE_scene_transform_orientation_find(
+          +scene, scene->orientation_slots->index_custom);
+    }
+
+    if (custom_orientation) {
+      float m[4][4] = {{0}}, mt[4][4];
+      unit_m4(m);
+      unit_m4(mt);  // Translation matrix
+
+      copy_m4_m3(m, custom_orientation->mat);
+      translate_m4(mt,
+                   custom_orientation->origin[0],
+                   custom_orientation->origin[1],
+                   custom_orientation->origin[2]);
+
+      mul_m4_series(rv3d->ucsmat, rv3d->viewmat, mt, m);
+    }
+    else {
+      // Invalid
+      v3d->ucs = 0;
+      copy_m4_m4(rv3d->ucsmat, rv3d->viewmat);
+    }
+  }
+  else {
+    copy_m4_m4(rv3d->ucsmat, rv3d->viewmat);
+  }
+
+
   /* update utility matrices */
   mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
   invert_m4_m4(rv3d->persinv, rv3d->persmat);
diff --git a/source/blender/editors/space_view3d/view3d_navigate_view_axis.cc b/source/blender/editors/space_view3d/view3d_navigate_view_axis.cc
index db9b8d94bb4..dffd4a51114 100644
--- a/source/blender/editors/space_view3d/view3d_navigate_view_axis.cc
+++ b/source/blender/editors/space_view3d/view3d_navigate_view_axis.cc
@@ -164,7 +164,8 @@ static int view_axis_exec(bContext *C, wmOperator *op)
   /* Use this to test if we started out with a camera */
   const int nextperspo = (rv3d->persp == RV3D_CAMOB) ? rv3d->lpersp : perspo;
   float quat[4];
-  ED_view3d_quat_from_axis_view(viewnum, view_axis_roll, quat);
+  Scene *scene = CTX_data_scene(C);
+  ED_view3d_quat_from_axis_view_transform(scene, v3d, viewnum, view_axis_roll, quat);
   axis_set_view(
       C, v3d, region, quat, viewnum, view_axis_roll, nextperspo, align_quat, smooth_viewtx);
 
diff --git a/source/blender/editors/space_view3d/view3d_utils.cc b/source/blender/editors/space_view3d/view3d_utils.cc
index 8a10d32e452..5582f526b2c 100644
--- a/source/blender/editors/space_view3d/view3d_utils.cc
+++ b/source/blender/editors/space_view3d/view3d_utils.cc
@@ -1425,6 +1425,33 @@ static float view3d_quat_axis[6][4][4] = {
 
 };
 
+bool ED_view3d_quat_from_axis_view_transform(Scene *scene, View3D *v3d, const char view,
+                                             const char view_axis_roll,
+                                             float r_quat[4])
+{
+  if (v3d->ucs) {
+    TransformOrientation *custom_orientation = nullptr;
+    if (scene->orientation_slots->type >= V3D_ORIENT_CUSTOM &&
+        scene->orientation_slots->index_custom != -1)
+    {
+      custom_orientation = BKE_scene_transform_orientation_find(
+          scene, scene->orientation_slots->index_custom);
+    }
+
+    if (custom_orientation) {
+      return ED_view3d_quat_from_axis_view_ucs(custom_orientation,view, view_axis_roll, r_quat);
+    }
+    else {
+      // Invalid ucs
+      return ED_view3d_quat_from_axis_view(view,view_axis_roll, r_quat);
+    }
+  }
+  else {
+    return ED_view3d_quat_from_axis_view(view, view_axis_roll, r_quat);
+  }
+}
+
+
 bool ED_view3d_quat_from_axis_view(const char view, const char view_axis_roll, float r_quat[4])
 {
   BLI_assert(view_axis_roll <= RV3D_VIEW_AXIS_ROLL_270);
@@ -1435,6 +1462,43 @@ bool ED_view3d_quat_from_axis_view(const char view, const char view_axis_roll, f
   return false;
 }
 
+bool ED_view3d_quat_from_axis_view_ucs(TransformOrientation *ts,
+                                       char view,
+                                       char view_axis_roll, float quat[4])
+{
+  float m[3][3];
+  float eul[3];
+
+  copy_m3_m3(m, ts->mat);
+  mat3_to_eul(eul, m);
+
+  switch (view) {
+    case RV3D_VIEW_TOP:
+      // XY
+      invert_m3(m);
+      mat3_to_quat(quat, m);
+      break;
+    case RV3D_VIEW_FRONT:
+      // ZX
+      rotate_eul(eul, 'X', M_PI / 2.0f);
+      eul_to_mat3(m, eul);
+      invert_m3(m);
+      mat3_to_quat(quat, m);
+      break;
+    case RV3D_VIEW_RIGHT:
+      // ZY
+      rotate_eul(eul, 'Z', M_PI / 2.0f);
+      rotate_eul(eul, 'X', M_PI / 2.0f);
+      eul_to_mat3(m, eul);
+      invert_m3(m);
+      mat3_to_quat(quat, m);
+      break;
+    default:
+      ED_view3d_quat_from_axis_view(view, view_axis_roll, quat);
+  }
+  return true;
+}
+
 bool ED_view3d_quat_to_axis_view(const float quat[4],
                                  const float epsilon,
                                  char *r_view,
@@ -1538,6 +1602,12 @@ bool ED_view3d_lock(RegionView3D *rv3d)
   return ED_view3d_quat_from_axis_view(rv3d->view, rv3d->view_axis_roll, rv3d->viewquat);
 }
 
+bool ED_view3d_lock_ucs(TransformOrientation *ts, RegionView3D *rv3d)
+{
+  ED_view3d_quat_from_axis_view_ucs(ts, rv3d->view, rv3d->view_axis_roll, rv3d->viewquat);
+  return true;
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
diff --git a/source/blender/editors/transform/transform_ops.cc b/source/blender/editors/transform/transform_ops.cc
index a56d649b78b..a7a67ef3d56 100644
--- a/source/blender/editors/transform/transform_ops.cc
+++ b/source/blender/editors/transform/transform_ops.cc
@@ -258,6 +258,8 @@ static int create_orientation_exec(bContext *C, wmOperator *op)
   const bool use_view = RNA_boolean_get(op->ptr, "use_view");
   View3D *v3d = CTX_wm_view3d(C);
   Scene *scene = CTX_data_scene(C);
+  const bool set_ucs = RNA_boolean_get(op->ptr, "set_ucs");
+  TransformOrientation *ts;
 
   RNA_string_get(op->ptr, "name", name);
 
@@ -268,7 +270,9 @@ static int create_orientation_exec(bContext *C, wmOperator *op)
     return OPERATOR_CANCELLED;
   }
 
-  if (!BIF_createTransformOrientation(C, op->reports, name, use_view, use, overwrite)) {
+
+  ts = BIF_createTransformOrientation(C, op->reports, name, use_view, use, overwrite);
+  if (ts == nullptr) {
     BKE_report(op->reports, RPT_ERROR, "Unable to create orientation");
     return OPERATOR_CANCELLED;
   }
@@ -279,6 +283,16 @@ static int create_orientation_exec(bContext *C, wmOperator *op)
     WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
   }
 
+  if (set_ucs) {
+    if (scene) {
+      // 0 = Global
+      v3d->ucs = BLI_findindex(&scene->transform_spaces, ts) + 1;
+    }
+    else {
+      BKE_report(op->reports, RPT_ERROR, "Cannot set ucs!");
+    }
+  }
+
   WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, nullptr);
 
   return OPERATOR_FINISHED;
@@ -305,6 +319,8 @@ static void TRANSFORM_OT_create_orientation(wmOperatorType *ot)
       "Use View",
       "Use the current view instead of the active object to create the new orientation");
 
+  RNA_def_boolean(ot->srna, "set_ucs", false, "Set as UCS", "Select as ucs after its creation");
+
   WM_operatortype_props_advanced_begin(ot);
 
   RNA_def_boolean(
diff --git a/source/blender/editors/transform/transform_orientations.cc b/source/blender/editors/transform/transform_orientations.cc
index 1f3b456e676..a8e66204a19 100644
--- a/source/blender/editors/transform/transform_orientations.cc
+++ b/source/blender/editors/transform/transform_orientations.cc
@@ -431,7 +431,7 @@ bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const floa
   return true;
 }
 
-bool BIF_createTransformOrientation(bContext *C,
+TransformOrientation* BIF_createTransformOrientation(bContext *C,
                                     ReportList *reports,
                                     const char *name,
                                     const bool use_view,
@@ -468,7 +468,7 @@ bool BIF_createTransformOrientation(bContext *C,
   if (activate && ts != nullptr) {
     BIF_selectTransformOrientation(C, ts);
   }
-  return (ts != nullptr);
+  return (ts);
 }
 
 TransformOrientation *addMatrixSpace(bContext *C,
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index 4dd7e16cb11..22dfc5cab51 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -39,6 +39,8 @@ typedef struct RegionView3D {
   /** Offset/scale for camera GLSL texture-coordinates. */
   float viewcamtexcofac[4];
 
+  float ucsmat[4][4];
+
   /** viewmat/persmat multiplied with object matrix, while drawing and selection. */
   float viewmatob[4][4];
   float persmatob[4][4];
@@ -358,6 +360,10 @@ typedef struct View3D {
 
   /** Runtime evaluation data (keep last). */
   View3D_Runtime runtime;
+
+  int ucs;
+  char _pad5[4];
+
 } View3D;
 
 /** #View3D::stereo3d_flag */
diff --git a/source/blender/makesrna/intern/rna_space.cc b/source/blender/makesrna/intern/rna_space.cc
index 92732bc9475..fe8f255bbfe 100644
--- a/source/blender/makesrna/intern/rna_space.cc
+++ b/source/blender/makesrna/intern/rna_space.cc
@@ -536,6 +536,10 @@ static const EnumPropertyItem rna_enum_curve_display_handle_items[] = {
     {0, nullptr, 0, nullptr, nullptr},
 };
 
+const EnumPropertyItem ucs_items[] = {
+    {0, "global", 0, "Global", "Use global as system coordinates"}, {0, NULL, 0, NULL, NULL}};
+
+
 #ifdef RNA_RUNTIME
 
 #  include <algorithm>
@@ -1551,6 +1555,44 @@ static void rna_SpaceView3D_use_local_collections_update(bContext *C, PointerRNA
   }
 }
 
+const EnumPropertyItem *rna_ucs_itemf(bContext *C,
+                                PointerRNA *ptr,
+                                PropertyRNA *prop,
+                                bool *r_free)
+{
+  Scene *scene = NULL;
+  ListBase *transform_spaces;
+  TransformOrientation *ts = NULL;
+  EnumPropertyItem tmp = {0, "", 0, "", ""};
+  EnumPropertyItem *item = NULL;
+  int i = 1, totitem = 0;
+
+  RNA_enum_items_add(&item, &totitem, ucs_items);
+
+  scene = CTX_data_scene(C);
+
+  if (scene) {
+    transform_spaces = &scene->transform_spaces;
+    ts = (TransformOrientation*) transform_spaces->first;
+  }
+
+  if (ts) {
+    RNA_enum_item_add_separator(&item, &totitem);
+
+    for (; ts; ts = ts->next) {
+      tmp.identifier = ts->name;
+      tmp.name = ts->name;
+      tmp.value = i++;
+      RNA_enum_item_add(&item, &totitem, &tmp);
+    }
+  }
+
+  RNA_enum_item_end(&item, &totitem);
+  *r_free = true;
+
+  return item;
+}
+
 static const EnumPropertyItem *rna_SpaceView3D_stereo3d_camera_itemf(bContext *C,
                                                                      PointerRNA * /*ptr*/,
                                                                      PropertyRNA * /*prop*/,
@@ -5287,6 +5329,14 @@ static void rna_def_space_view3d(BlenderRNA *brna)
   RNA_def_property_ui_text(
       prop, "Overlay Settings", "Settings for display of overlays in the 3D viewport");
 
+
+  prop = RNA_def_property(srna, "ucs", PROP_ENUM, PROP_NONE);
+  RNA_def_property_enum_sdna(prop, NULL, "ucs");
+  RNA_def_property_enum_items(prop, ucs_items);
+  RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_ucs_itemf");
+  RNA_def_property_ui_text(prop, "UCS", "User Coordinate System");
+  RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
   rna_def_space_view3d_shading(brna);
   rna_def_space_view3d_overlay(brna);
 
